动态代理简要总结

何为代理?

  • 说到代理,开发中随处可见。nginx服务器正向代理、反向代理,jdk5动态代理、cglib动态代理等。面试中也常问何为代理模式?
  • 代理举例就是说同学A拥有买东西的能力,但是他不在自己做,让同学B去帮忙买回来。这个同学B就是代理。
  • 代理有什么好处呢?同上,如果让同学B去帮忙买东西,同学B是不是就可以在买东西的时候动手脚啦?比如想办法花更少的钱买到一样的东西,多的就成B同学的了,大赚一笔。在代码中其实也一样,这个“动手脚”就是“多余”的工作,既不影响完成帮A同学买东西,还能赚钱“搞事”。将真正的实现类的方法抽离出来,需要有前置处理可以直接在代理中处理,通过代理可以让调用者与实现者之间解耦。参考博文:代理模式

动态代理

  • 自我理解是所谓的动态代理,其实就是在代理模式中扮演代理的角色是根据需求动态去创建,不是一早定死的。在实际的使用中只需去使用不需要去关注细节实现,在jdk、三方包中已经实现好。(喜欢研究源码的兄弟可以看看源码实现,其实也蛮不错的)

  • JDK动态代理简单实现代码:

    
    public class Main {
        public static void main(String[] args) {
            Student student = new Student();
            StudentHandler studentHandler = new StudentHandler(student);
            Hello hello = (Hello) Proxy.newProxyInstance(student.getClass().getClassLoader(), student.getClass().getInterfaces(), studentHandler);
            System.out.println("结果:" + hello.sayHello());
        }
    
        /**
         * 接口
         */
        public interface Hello {
            Boolean sayHello();
        }
    
        /**
         * 学生实现类
         */
        public static class Student implements Hello {
            public Boolean sayHello() {
                System.out.println("student say hello");
                return false;
            }
        }
    
        /**
         * 学生代理类
         */
        public static class StudentHandler implements InvocationHandler {
    
            private Object student;
    
            public StudentHandler(Object student) {
                this.student = student;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //这里可以判断方法进行代理前置操作
                System.out.println("调用方法:" + method.toString());
                Object invoke = method.invoke(student, args);
                System.out.println("Student方法返回:" + invoke);
                return true;
            }
        }
    }
    
    

输出:

调用方法:public abstract java.lang.Boolean com.li.blog.Main$Hello.sayHello()
student say hello
Student方法返回:false
结果:true
  • Proxy.newProxyInstance方法动态生成了动态类。实现InvocationHandler 类中的invoke方法在调用方法时就会进入次方法,在这个方法中可以进行方法前置处理,比如参数返回值等。源码阅读可参考:彻底搞懂jdk动态代理并自己动手写一个动态代理 从上面输出可以看出,调用的方法,返回值也做了处理。
  • 比较常见的动态代理的实现就是JDK动态代理、cglib动态代理

JDK动态代理、cglib动态代理简单比较

JDK动态代理

  • 最小化依赖关系,减少依赖意味着简化开发和维护,JDK 本身的支持,可能比 cglib 更加可靠。
  • 平滑进行 JDK 版本升级,而字节码类库通常需要进行更新以保证在新版 Java 上能够使用。
  • 代码实现简单。

cglib动态代理

  • 有的时候调用目标可能不便实现额外接口,从某种角度看,限定调用者实现接口是有些侵入性的实践,类似 cglib 动态代理就没有这种限制。
  • 只操作我们关心的类,而不必为其他相关类增加工作量。
  • 高性能。

我工作中遇到使用动态代理的地方

  • Spring AOP 实现默认使用JDK动态代理,可以设置使用cglib
  • Spring JPA 持久层接口解析时
  • Mybatis 接口xml映射

猜你喜欢

转载自blog.csdn.net/qq_28325291/article/details/83154518