`
candy1234
  • 浏览: 3735 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

Spring AOP源码理解深入

阅读更多

         AOPAspect Oriented Programming的缩写,面向切面编程,它的思想是将与业务逻辑无关的功能抽象出来,然后通过配置指定哪些功能怎样应用到业务逻辑方法中。如常用的日志记录、安全控制、事务处理,它们都是一些通用的与业务逻辑无关的功能,可以将其抽象出来,不必要在所有的方法代码中都重复调用一次(如果后期发现接口、逻辑有修改,是不是所有的调用代码都要调整?)。我们可以通过一定的配置指定哪些方法需要记录日志,哪些需要安全控制,哪些需要配置事务;可以指定在方法执行前、后或异常抛出时进行调用;总之,可以很灵活的进行全局配置,达到将独立功能嵌入到现有逻辑中。

         AOP是一种思想,每个人都可以实现它,只要最终能满足自己要求,可以降低程序的耦合、提高可重用性。但是,这样有一个问题,如果哪天发现别人的实现比自己的实现更好,比如性能更快、更简洁、更容易扩展,就想直接切换过去,可在切换的时候才发现根本不能简单透明(不修改项目现有代码或很少修改)的调整。因为,虽然功能一样,但是接口、配置都不一致。因此,为了更好的促进AOP的发展,统一规范,出现了一个叫AOP联盟的组织,负责制定AOP相关接口规范,对AOP编程思想进行了高度抽象,提出通知、连接点、拦截器等概念,整个接口API很简洁,如图所示:

 

现在AOP的实现很多,有Spring AOPAspectJAspectWerkz等,下面主要分析Spring AOP的实现。

        

         要将抽象的与业务逻辑无关的功能(如上所说的日志记录)动态的应用到业务逻辑代码中,常用的技术就是代理。Spring AOP实现也是采用代理方式,代理目标对象,根据配置将添加的功能通过代理调用。AOP代理就是一个代理,只是基于AOP思想生成而已。

         首先,介绍几个AOP术语:

         1Advice(通知),定义具体要做什么,如上面所说的日志记录、安全控制。有时也称为“增强”,对目标方法进行功能增强。

         2Joinpoint(连接点),定义通知执行的代码位置,如在哪个方法执行。

         3Pointcut(切点),定义通知在哪些连接点上执行,即定义连接点的一个集合,通常配置一个正则表达式匹配一系列方法集合。

         4Advisor(通知器),将通知和切点关联起来,定义了哪个通知用于哪个切点。

        

         接着,看看AOP代理是如何生成的。

         Spring提出了一个工厂beanFactoryBean)的概念,既是一个创建bean的工厂,又是BeanFactory的一个bean。通过它可以完全自定义需要的任何bean,不再受bean标签指定的特定class束缚,因为在获取工厂bean的时候实际上返回的是getObject()返回的对象,而不是工厂bean本身。因此,创建bean代理也可以通过类似的方式实现,在getObject()中对目标bean进行代理,将要增加的功能添加到代理对象。ProxyFactoryBean就是创建AOP代理具体实现,比如常见的属性targetName(代理目标)、interceptorNames(通知器/通知名称),创建过程为:

         1、根据配置的通知器(interceptorNames值)构造一个拦截器(通知器)链,实际调用的时候会依次执行。其实就是根据配置的通知器名称找到对应的bean,并添加到List集合。

         2、创建代理对象,并在调用时候加入拦截器的调用。

         如果是接口,就直接采用JDK动态代理;否则就采用CGLIB生成代理。代理创建好了,对拦截器链的调用才是核心,这里以JDK代理为例分析拦截器链是怎么调用的。在ReflectiveMethodInvocationproceed方法中,会逐个执行拦截器的拦截方法,但是在执行拦截方法之前,会对代理方法进行匹配校验,满足的才进行拦截。整个递归迭代原理是在MethodInvocation(看具体实现ReflectiveMethodInvocation)的proceed方法中,调用MethodInterceptorinvoke方法,在invoke方法中,返回MethodInvocationproceed结果,而在proceed的处理中,又会进行下一个MethodInterceptor调用。通过代码更容易理解,如下:

ReflectiveMethodInvocation的proceed方法(部分逻辑):
public Object proceed() throws Throwable {
    //从拦截器链中依次取出拦截器
    Object interceptorOrInterceptionAdvice =          this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    //调用拦截器的拦截方法
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    }
}
MethodBeforeAdviceInterceptor的invoke方法:
public Object invoke(MethodInvocation mi) throws Throwable {
    //该拦截器的通知具体调用地方,比如此处为方法调用前置通知,那么增强的功能就在方法执行前调用
    this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
    return mi.proceed();
}

          

         简单的讲,AOP代理就是添加了一个拦截器链调用,而Spring AOP拦截器其实就是Spring实现的Advice。下面展示Spring Advice实现类层次关系图:


 

 

上图左边是AOP规范接口,右边是Spring AOP实现。Spring将通知(功能增强)和拦截器分开实现,然后采用拦截器包装通知的方式,又抽象了一层功能,降低了代码耦合,增加了使用的灵活性。最后,为了使用拦截器链的方便,为每个通知配置了一个适配器,并将适配器注册到全局注册表DefaultAdvisorAdapterRegistry中,而AOP代理在根据配置的通知器(Advisor)获取匹配的通知(Advice)时会通过MethodInterceptor[] getInterceptors(Advisor advisor)方法转换为标准MethodInterceptor,这就取得了拦截器链。

  • 大小: 15.6 KB
  • 大小: 62.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics