1 bean的生命周期
2 方法调用的事务失效。
从上面的分析可以看出,methodB没有被AopProxy通知到,
导致最终结果是:
被Spring的AOP增强的类,在同一个类的内部方法调用时,其被调用方法上的增强通知将不起作用。
问题的原因已经找到,其实,我理想中的AOP实现,应该是下面这样:
只要一个Cglib增强对象就好,对于Java代理方式,我的选择是毫不犹豫的抛弃。
至于前面的事务问题,只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务,那么一切OK。
3 springAOP的实现原理——动态代理
3.1 实现原理
通过动态代理来实现,如果为某个bean配置了切面,那么在创建这个bean的时候,实际上是创建了他的代理对象,调用他的方法实际上是调用了代理类重写的方法。
3.2 JDK动态代理
JDK实现动态代理需要两个组件,首先第一个就是InvocationHandler接口。我们在使用JDK的动态代理时,需要编写一个类,去实现这个接口,然后重写invoke方法,这个方法其实就是我们提供的代理方法。然后JDK动态代理需要使用的第二个组件就是Proxy这个类,我们可以通过这个类的newProxyInstance方法,返回一个代理对象。生成的代理类实现了原来那个类的所有接口,并对接口的方法进行了代理,我们通过代理对象调用这些方法时,底层将通过反射,调用我们实现的invoke方法。
优点: JDK自带,不需要依赖任何第三方; 通过反射生成代理类的速度比较快。
缺点: 需要代理的类必须是实现接口的; 只能为接口的方法进行代理,如果为此类中不是接口的方法配置了切面,这个方法将不会被织入; 反射(需要执行回调)执行的效率比较低。
3.3 CGLIB
JDK的动态代理存在限制,那就是被代理的类必须是一个实现了接口的类,代理类需要实现相同的接口,代理接口中声明的方法。若需要代理的类没有实现接口,此时JDK的动态代理将没有办法使用,于是Spring会使用CGLib的动态代理来生成代理对象。CGLib直接操作字节码(ASM字节码生成卡 框架),生成类的子类,重写类的方法完成代理。
优点: 类不用实现接口; 只要是可以重写的类,都可以进行代理; 执行效率高。
缺点: 如果是final类或者方法的,则无法搞; 生成代理类比较慢。
总结: 使用CGLIB,因为我们 大部分类都是单例的,并不需要频繁的创建。