Spring源码学习(二)------ AOP

原创 2011年01月13日 20:54:00

AOP有些特有的概念,如:advisor、advice和pointcut等等,使用或配置起来有点绕,让人感觉有些距离感,其实它的实现就是一组标准的设计模式的组合使用:Factory、Proxy、Chain of Responsibility,只要搞清楚这几个设计模式,读AOP的源码是比较容易的。

首先看看ProxyFactoryBean这个类,这是AOP使用的入口,从AOP拿到的bean object就是ProxyFactoryBean.getObject得到的,从这条线下去,发现AOP就是通过Proxy模式从实际要执行的target做了包装,而Proxy还不止一套方案,通过Factory封装了两套Proxy实现方案:JDK 动态Proxy和Cglib Proxy。有两套实现主要是因为JDK 动态Proxy必须要target实现某个接口,如果不满足这个条件就会用Cglib增强字节码的方式来实现proxy。

就拿JDK Proxy为例,Spring AOP使用了标准的JDK提供的动态Proxy方案,我们先看看标准的动态Proxy是什么样子,看下面类图:

Cilent通过Proxy.newProxyInstance(classLoader, proxiedInterfaces, invocationHandler);就能拿到target的proxy object,在执行target的方法时就会先执行到DynamicProxy中的invoke方法从而实现代理包装。基于这个道理来看Spring AOP的实现,实际上就是标准地基于这个方式来做的,Spring AOP的所有花招都体现在JdkDynamicAopProxy.invoke中(当然在Cglib中是通过callback来做的,道理类似)。

通过看JdkDynamicAopProxy.invoke的源码会发现,Spring AOP的各种花招是通过Chain of Responsibility模式串起来的,先看看一个标准的Chain of Responsibility是什么样子,看下面的类图:

而Chain of Responsibility的关键在于Invocation与Interceptor的配合,主要原则就两条:

1)Invocation需要维护Interceptor集合和游标,每次调用invoke时需要先调用游标所在的Interceptor.invoke,如果游标已超过最后一个Interceptor,则调用实际target的方法

2)Interceptor的invoke中除了要执行自己的拦截逻辑,还要通过Invocation.invoke把调用传递下去,拦截的灵活性就体现在Invocation.invoke执行与否和执行的顺序。

以上逻辑通过时序图来看,如下图所示:

理解Chain of Responsibility后再来看Spring AOP,JdkDynamicAopProxy.invoke做的事情就是以上Client做的事情,

1)首先通过this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);组装interceptor chain

2)然后new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);得到invocation

3)最后通过invocation.proceed();启动责任链

而Spring AOP的那些概念都体现在组装interceptor chain中,advisor、advice和pointcut无非就是帮助你描述如何对Target进行拦截,对这一块感兴趣的朋友可以好好读读里面的代码。另外,Spring AOP提供了各种各样的Interceptor,来实现各种形式的横切,具体做法可以详细看看各Interceptor的实现。

综上所述,整个流程如下图所示:

总之,把握了Factory、Proxy、Chain of Responsibility的运用也就把握了Spring AOP的实现原理,道理虽然简单,但其中的精髓和原由还是值得我们继续深思的。

相关文章推荐

spring源码剖析(六)AOP实现原理剖析

Spring的AOP实现原理,酝酿了一些日子,写博客之前信心不是很足,所以重新阅读了一边AOP的实现核心代码,而且又从网上找了一些Spring Aop剖析的例子,但是发现挂羊头买狗肉的太多,标题高大上...

(八)Spring核心框架 - AOP的原理及源码解析

一、AOP的体系结构 如下图所示:(引自AOP联盟) 层次3语言和开发环境:基础是指待增加对象或者目标对象;切面通常包括对于基础的增加应用;配置是指AOP体系中提供的配置环境或者编织配置,通过该配...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

深入浅出Mybatis-插件原理

Mybatis采用责任链模式,通过动态代理组织多个拦截器(插件),通过这些拦截器可以改变Mybatis的默认行为(诸如SQL重写之类的),由于插件会深入到Mybatis的核心,因此在编写自己的插件前最...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Spring源码学习之spring设计理念和整体架构

1.Spring的设计理念:在Java EE的应用开发中,支持POJO和使用JavaBean的开发方式, 使应用面向接口开发,充分支持00 ( 面向对象) 的设计方法。 2.Spring的整体架构...

Spring学习1:Spring源码阅读环境搭建

Spring已经将源码从svn迁移到GitHub了。而且也改为基于Gradle构建项目,取代了之前的Ant+Ivy系统,所以要构建Spring源码环境首先要安装GitHub和Gradle。 安装...

spring源码学习之路---深入AOP(终)

作者:zuoxiaolong8810(左潇龙),转载请注明出处。                 上一章和各位一起看了一下springAOP的工作流程,当我们给出AOP相关的配置以后,直接从IOC容...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

SPRING源码学习之路(二)

上一篇,已经对IOC容器的初始化过程有个大体认识,接着看IOC容器的依赖注入。       依赖注入的触发是在用户第一次向容器索要Bean时才触发,当然也可以设置lazy-init让容器提前完成B...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Spring源码学习(二)------ AOP
举报原因:
原因补充:

(最多只允许输入30个字)