spring AOP的实现原理

姓名:陈中娇   班级:软件151

基于代理(Proxy)的AOP实现

首先,这是一种基于代理(Proxy)的实现方式。下面这张图很好地表达了这层关系:

Spring AOP的两种实现方式

Spring AOP有两种实现方式:

  • 基于接口的动态代理(Dynamic Proxy)
  • 基于子类化的CGLIB代理

我们在使用Spring AOP的时候,一般是不需要选择具体的实现方式的。Spring AOP能根据上下文环境帮助我们选择一种合适的。那么是不是每次都能够这么”智能”地选择出来呢尽然,下面的例子就反映了这个问题:

在上述代码中,我们为原来的Bean实现了一个新的接口,这个接口中并没有定义任何方法。这个时候,再次运行相关测试代码的时候就会出现异常(摘录了部分异常信息):

也就是说在Test类中对于Bean的Autowiring失败了,原因是创建SampleBeanTest Bean的时候发生了异常。那么为什么会出现创建Bean的异常呢常信息来看并不明显,实际上这个问题的根源在于Spring AOP在创建代理的时候出现了问题。

这个问题的根源可以在这里得到一些线索:

Spring AOP Reference – AOP Proxies

文档中是这样描述的(每段后加上了翻译):

Spring AOP defaults to using standard JDK dynamic proxies for AOP proxies. This enables any interface (or set of interfaces) to be proxied.

Spring AOP默认使用标准的JDK动态代理来实现AOP代理。这能使任何借口(或者一组接口)被代理。

Spring AOP can also use CGLIB proxies. This is necessary to proxy classes rather than interfaces. CGLIB is used by default if a business object does not implement an interface. As it is good practice to program to interfaces rather than classes; business classes normally will implement one or more business interfaces. It is possible to force the use of CGLIB, in those (hopefully rare) cases where you need to advise a method that is not declared on an interface, or where you need to pass a proxied object to a method as a concrete type.

Spring AOP也使用CGLIB代理。对于代理classes而非接口这是必要的。如果一个业务对象没有实现任何接口,那么默认会使用CGLIB。由于面向接口而非面向classes编程是一个良好的实践;业务对象通常都会实现一个或者多个业务接口。强制使用CGLIB也是可能的(希望这种情况很少),此时你需要advise的方法没有被定义在接口中,或者你需要向方法中传入一个具体的对象作为代理对象。

因此,上面异常的原因在于:

强制使用CGLIB也是可能的(希望这种情况很少),此时你需要advise的方法没有被定义在接口中。

我们需要advise的方法是SampleBean中的advicedMethod方法。而在添加接口后,这个方法并没有被定义在该接口中。所以正如文档所言,我们需要强制使用CGLIB来避免这个问题。

强制使用CGLIB很简单:

向注解中添加属性即可。 
CGLIB实现AOP代理的原理是通过动态地创建一个目标Bean的子类来实现的,该子类的实例就是AOP代理,它建立起了目标Bean到Advice的联系。

当然还有另外一种解决方案,那就是将方法定义声明在新创建的接口中并且去掉之前添加的:

  • JDK动态代理
  • 关于动态代理和CGLIB这两种方式的简要总结如下:

    • JDK动态代理(Dynamic Proxy)

      • 基于标准JDK的动态代理功能
      • 只针对实现了接口的业务对象
    • CGLIB

      • 通过动态地对目标对象进行子类化来实现AOP代理,上面截图中的即为动态创建的一个子类
      • 需要指定来强制使用
      • 当业务对象没有实现任何接口的时候默认会选择CGLIB

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览93566 人正在系统学习中 相关资源:pre.js:JSCSS的高效,弹性资源预加载器-其它代码类资源-CSDN文库

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2017年5月22日
下一篇 2017年5月22日

相关推荐