之前我们在Spring AOP简介里面写了一个简单的面向切面编程的小栗子,其实AOP的核心是其实现了两种代理模式:JDK和CGLIB动态代理
在了解这两种动态代理之前,我们先了解下什么是代理:
代理和现实生活中的中介有很大的类似,你买房子、卖房子,可以自己去操作,但是需要了解和买卖房产无关的细节,如契税等,而找一个中介,则不用关心这些与买卖房产无直接关系的中间细节,只关心业务本身。-----这是不是就是我们切面编程想要达到的效果?
那么代理又分两种:静态代理和动态代理
静态代理:一个代理类只能对一个业务接口的实现类进行包装,属于“硬编码”,如果有多个业务接口的话就要定义很多实现类和代理类才行;而且因为代理类里面代理处置的事情经常是共同的,这样多个代理类就会有很多重复代码
动态代理:它能代理所有实现类的方法调用:根据传进来的业务实现类和方法名进行具体调用,而不再是对一个具体的业务接口实现类进行包装,这样就大大增加了代理类的灵活性
好了,说了那么多代理的概念,现在我们来说说Spring AOP里面这两个代理类:
JdkDynamicAopProxy:实现了InvocationHandler接口,将被代理对象和拦截器作为参数传入,然后生成代理,是在程序调用到代理类对象时才由JVM真正创建,我们称之为JDK动态代理
绑定业务类并返回一个代理类:
实现invoke完成对业务方法的代理调用并实现代理类的功能:
CglibAopProxy:实现了Cglib的MethodInterceptor接口,使用了CGLIB加强器来创建动态代理类
然后通过回调来使用业务类(父类)中的方法,完成代理操作
在Spring AOP中,如果不是强制配置<aop:aspectj-autoproxy proxy-target-class="true"/>,则Spring回根据判断targetClass(具体业务类)是否有实现接口来确定使用哪一种代理,如果实现了接口则使用JDK动态代理,如果没有实现接口则使用Cglib代理,所以我们一般会配置为、<aop:aspectj-autoproxy />,将选择权交给Spring
PS:由于Cglib代理是利用ASM字节码生成框架在内存中生成一个需要被代理类的子类完成代理,而JDK动态代理是利用反射原理完成动态代理,所以Cglib创建的动态代理对象性能比JDk动态代理动态创建出来的代理对象新能要好的多,但是对象创建的速度比JDk动态代理要慢,所以,当Spring使用的是单例情况下可以选用Cglib代理,反之使用JDK动态代理更加合适。(JDK7以后版本,代理对象性能差异已经不很明显了,反而CGLIB比较新的版本,动态代理对象的创建速度比JDK要快,我是在CGLIB3.2.6和JDK8版本的基础上测试的)
同时还有一个问题,被final修饰的类只能使用JDK动态代理,因为被final修饰的类不能被继承,而Cglib则是利用的继承原理实现代理的,否则会报如下异常
有需要资料的可以加群:1023705513