Bootstrap

jdk、cglib动态代理介绍

在 Java 中,动态代理可以使用两种主要的方式实现:JDK 动态代理和 CGLIB 动态代理。下面详细介绍这两种动态代理方式,并提供相应的 Java 代码示例。

JDK 动态代理

JDK 动态代理是使用 Java 标准库中的 java.lang.reflect.Proxy 类来生成代理对象的机制。它要求目标类实现一个或多个接口,代理对象会实现这些接口,并将方法调用转发到 InvocationHandler 的实现类上。

  1. 创建一个接口,定义要被代理的方法。
  2. 创建一个实现 InvocationHandler 接口的类,实现 invoke 方法来实现方法的拦截和增强逻辑。
  3. 使用 Proxy.newProxyInstance() 方法创建代理对象,传入目标类的类加载器、接口数组和实现 InvocationHandler 的对象。

示例代码如下:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Hello {
    void sayHello();
}

class MyInvocationHandler implements InvocationHandler {
    private final Hello target;

    public MyInvocationHandler(Hello target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before calling sayHello()");
        Object result = method.invoke(target, args);
        System.out.println("After calling sayHello()");
        return result;
    }
}

public class JdkDynamicProxyExample {
    public static void main(String[] args) {
        Hello hello = new HelloImpl();
        Hello proxyHello = (Hello) Proxy.newProxyInstance(
                hello.getClass().getClassLoader(),
                hello.getClass().getInterfaces(),
                new MyInvocationHandler(hello)
        );

        proxyHello.sayHello();
    }
}

class HelloImpl implements Hello {
    @Override
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

CGLIB 动态代理

CGLIB(Code Generation Library)是一个字节码生成库,它可以在运行时动态生成类的子类,用于实现代理。CGLIB 动态代理要求目标类不是 final 类型,并且不需要实现接口。

  1. 导入 CGLIB 相关库。
  2. 创建一个继承目标类的子类,重写要被代理的方法,并在方法中添加拦截和增强逻辑。
  3. 使用 CGLIB 的 Enhancer 类创建代理对象。

示例代码如下:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

class Hello {
    public void sayHello() {
        System.out.println("Hello, world!");
    }
}

class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before calling sayHello()");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After calling sayHello()");
        return result;
    }
}

public class CglibDynamicProxyExample {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Hello.class);
        enhancer.setCallback(new MyMethodInterceptor());

        Hello proxyHello = (Hello) enhancer.create();
        proxyHello.sayHello();
    }
}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;