一.静态代理。
静态代理常用的如:三层架构。
缺点是不符合开闭原则。
二.动态代理
1.JDK动态代理 (实现InvocationHandler接口,实现invoke方法,被代理的类需要集成一个接口)
Proxy是一个工具类,实际上的作用就是动态生成字节码并编译执行新生成的类。
这里传入的clzz.getInterfaces() 就是为了获取到接口并且为新生成的类提供生成方法。
原理:动态生成字节码生成一个新的类,$Proxy类,$Proxy实现了被调用类的接口,通过反射,生成接口里所有的方法,调用目标方法其实就是在调用$Proxy这个新生成的类的方法,所以JDK动态代理一定要实现一个接口。
可以通过invoke()//代理,before()//代理前,after()//代理后 ,进行对代理方法的统一增强,有点类似Spring的AOP。
2.CGLib动态代理:
跟JDK不同的是CGLib动态代理目标类不需要实现一个统一的接口,这样就不会限制目标类,同时代理类需要实现MethodInterceptor接口,同时CGLib需要借助生成动态字节码的类是Enhancer。
CGLib会通过Enhancer工具类使用ASM框架动态生成三个class,所以在生成代理类的阶段,CGLib比JDK动态代理效率低,因为生成复杂。生成的代理类实现了目标对象,覆盖目标类,在方法调用的时候生成另一个类调用代理方法。CGLib在调用效率上比JDK动态代理上要高,因为代理方法在被调用时生成所有逻辑的fastclass文件,不需要再经过反射调用。
CGLib动态代理虽然可以在目标类上取消实现接口的约束,但是依然有弊端,那就是不能代理final的方法。
三.跟Spring的联系
1.当bean实现了接口时,Spring就使用JDK动态代理,如果没有实现接口,Spring则使用CGLib动态代理。
2.可以在配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>表示强制使用CGLib动态代理。
四.动态代理的优点
1.代理模式可以将代理类和真实被调用的对象分离
2.一定程度降低了系统的耦合程度,易于扩展
3.代理可以起到保护目标对象的作用
4.增强目标对象的职责
动态代理的缺点:
1.类的数量增加
2.在客户端与目标对象之间增加了代理,使处理速度变慢
3.增加了系统复杂度
五.个人理解
实际场景中很少能真正的使用扫动态代理,有一种场景,就是当你接手一个项目,涉及到其他人的写的方法,而这个方法又过于繁琐,逻辑复杂,就可以使用代理的方式对这个方法进行增强,在这个方法之前与之后做修改。而原来调用这个方法的地方可以继续工作,以后需要调用到这个增强的地方就可以通过代理的方法使用。