JDK 动态代理和 CGLib 动态代理

    JDK 动态代理是 JVM 根据传进来的对象,动态的创建对象的代理对象并返回。
    CGLib 动态代理比较复杂,它是通过继承的方式来实现类的代理

JDK 动态代理

实现步骤:

  1. 定义业务接口
  2. 实现业务接口
  3. 定义代理类
public class JDKProxy {
    /**
     * @param obj
     *            需要代理的对象
     * @return 返回代理对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T proxy(final T obj) {
        return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * proxy: method:被代理对象的方法 args:被代理对象的方法需要的参数
                     */
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // 增强逻辑
                        // 调用原方法
                        Object result = method.invoke(obj, args);
                        // 增强逻辑
                        return result;
                    }
                });
    }
}

CGLib 动态代理

原理:

  1. 自定义类 A
  2. 使用 CGLib 在内存中创建一个没有名称的动态类 B,返回 B 的引用 C
  3. 通过引用 C 指定 A 和 B 的继承结构,B extends A
  4. 定义方法调用拦截,在拦截中增强逻辑,并执行原操作
public class CGLibProxy {
    @SuppressWarnings("unchecked")
    public static <T> T proxy(Class<T> clazz) {
        // 在内存中创建动态类
        Enhancer dynamicClass = new Enhancer();
        // 设置动态类的父类
        dynamicClass.setSuperclass(clazz);
        // 创建方法调用拦截
        Callback callback = new MethodInterceptor() {
            /**
             * proxy:代理对象
             * method:被拦截的方法对象
             * args:方法参数
             * methodProxy:被拦截的方法对象的代理对象
             */
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
                    throws Throwable {
                // 增强逻辑
                // 调用父类的方法,由于继承重写的特性,最终会执行子类的方法
                // 不使用这个方法:methodProxy.invoke(proxy, args);
                Object result = methodProxy.invokeSuper(proxy, args);
                // 增强逻辑
                return result;
            }
        };
        dynamicClass.setCallback(callback);
        // 返回动态类实例
        return (T) dynamicClass.create();
    }
}

    如何理解 CGLib 动态代理的实现?

// 例如:Student extends Person
// 创建 Student 对象,但以 Person 展现
Person p = new Student();
// 我们知道,如果 Person 中没有 speak()方法,那么这里编译不会通过
// 程序运行时,并不会调用 Person 中 speak()方法的实现,而是调用 Student 中的实现
p.speak();

// 从继承和重写上看,我们应该知道为什么在 CGLib 中
// 不使用这个方法:methodProxy.invoke(proxy, args);
// 而调用 invokeSuper 方法的原因
Object result = methodProxy.invokeSuper(proxy, args);

猜你喜欢

转载自blog.csdn.net/qq_30038111/article/details/80038978