JDK动态代理和CGLib动态代理

墨蓝 2022-05-26 01:14 447阅读 0赞
  1. JDK 动态代理是 JVM 根据传进来的对象,动态的创建**对象的代理对象**并返回。
  2. CGLib 动态代理比较复杂,它是通过继承的方式来实现**类的代理**。

JDK 动态代理

实现步骤:

  1. 定义业务接口
  2. 实现业务接口
  3. 定义代理类

    public class JDKProxy {

    1. /** * @param obj * 需要代理的对象 * @return 返回代理对象 */
    2. @SuppressWarnings("unchecked")
    3. public static <T> T proxy(final T obj) {
    4. return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
    5. new InvocationHandler() {
    6. /** * proxy: method:被代理对象的方法 args:被代理对象的方法需要的参数 */
    7. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    8. // 增强逻辑
    9. // 调用原方法
    10. Object result = method.invoke(obj, args);
    11. // 增强逻辑
    12. return result;
    13. }
    14. });
    15. }

    }

CGLib 动态代理

原理:

  1. 自定义类 A
  2. 使用 CGLib 在内存中创建一个没有名称的动态类 B,返回 B 的引用 C
  3. 通过引用 C 指定 A 和 B 的继承结构,B extends A
  4. 定义方法调用拦截,在拦截中增强逻辑,并执行原操作

    public class CGLibProxy {

    1. @SuppressWarnings("unchecked")
    2. public static <T> T proxy(Class<T> clazz) {
    3. // 在内存中创建动态类
    4. Enhancer dynamicClass = new Enhancer();
    5. // 设置动态类的父类
    6. dynamicClass.setSuperclass(clazz);
    7. // 创建方法调用拦截
    8. Callback callback = new MethodInterceptor() {
    9. /** * proxy:代理对象 * method:被拦截的方法对象 * args:方法参数 * methodProxy:被拦截的方法对象的代理对象 */
    10. public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
    11. throws Throwable {
    12. // 增强逻辑
    13. // 调用父类的方法,由于继承重写的特性,最终会执行子类的方法
    14. // 不使用这个方法:methodProxy.invoke(proxy, args);
    15. Object result = methodProxy.invokeSuper(proxy, args);
    16. // 增强逻辑
    17. return result;
    18. }
    19. };
    20. dynamicClass.setCallback(callback);
    21. // 返回动态类实例
    22. return (T) dynamicClass.create();
    23. }

    }

    如何理解 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);

发表评论

表情:
评论列表 (有 0 条评论,447人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JDK动态代理CGLib动态代理

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