AOP专题

Spring的AOP实现

  前面我们阐述了动态代理实现AOP机制。 现在看看Spring如何实现AOP的。

AOP的几个名词:

  • Pointcut类似触发器,是事件Event发生源,一旦pointcut被触发,将会产生相应的动作Action,这部分Action称为Advice。
  • Advice在AspectJ有三种:before、 after、Around之分 。Advice分:
    (1) Interceptor 是拦截器,动态代理做拦截器。
    (2). Introduction修改一个类,以增加字段、方法或构造或者执行新的接口,包括Mixin实现
  • AOP是将通用功能和特殊功能在编码时期分离,在运行时刻需要装配,这个阶段称为weaving
    instrumentor - 用来实现weaving功能的工具。

结合前面动态代理实现,Advice相当于DynamicProxyTemplate这个类,它调用拦截器,然后在被拦截的目标对象之前或之后执行:

                 interceptor.beforeAction(method, args);//这里是一个joinpoint
                     o = method.invoke(obj, args);//BuinessOne.mymethod();
                     interceptor.afterAction(method, args);;//这里是一个joinpoint

不过在Spring中,这段拦截位置是在XML配置或元注解中配置的,更加灵活。如下图:

下面结合Spring,对AOP用语进行详细总结如下:

  • 切入点(Joinpoint): 程序执行的某个特定位置,如类的初始化前后、方法的调用前后、抛异常后。Spring只支持方法切入点。
  • 切面(Pointcut): Spring中通过org.springframework.aop.Pointcut进行描述
  • 激活与处理(Advice): 植入到目标切入点上的一段程序。Spring提供的接口都带有方位名:BeforeAdvice,AfterReturnAdvice,ThrowsAdvice。
  • 目标(Target): 切入的逻辑植入的目标类
  • 引入(Introduction): 一种特殊的Advice,可以为类添加一些属性和方法
  • 织入(Weaving): 将Advice与连接点结合的方法.Spring使用动态代理实现,AspectJ在编译时和类加载时实现。
  • 方面(Aspect): Pointcut+Advice

Spring的AOP实现内部机制:

  • J2SE 动态代理
    使用到的类:Proxy,InvocationHandler
    使用interception chain实现Advice。
    只能对接口进行代理
  • CGLIB 代理(第三方库 性能快) 可以直接对Class进行代理
  • AspectJ 需要用特定的Java编译器,在编译时混合代码

Spring的AOP类图:


下面我们看看Spring的Pointcuts切入点这个类;

Pointcuts有两个方法:

  1. 将advice固定于某个特定的类ClassFilter,这是用来寻找匹配被拦截的类
  2. MethodMatcher是寻找被拦截的目标对象方法是否和需要拦截的方法一致。matches(Method, Class) 方法通常用于测试pointcut是否和目标类的方法匹配. 它是在AOP proxy 被创建时执行,这样可以避免每次方法调用都进行测试执行。最后一个matches是每次方法调用时都被执行

切入面有两种:

  1. 静态切入面:
    (1).NameMatchMethod 根据方法名字切入
    (2).根据方法的正则表法式切入
  2. 动态切入面

静态切入pointcuts

代码:

相应配置:

正则表达式切入法

  • <bean id="settersAndAbsquatulateAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

        <property name="advice">
         <ref local="beanNameOfAopAllianceInterceptor"/> </property>
        <property name="patterns">
               <list>
                  <value>.*get.*</value>        
                  <value>.*absquatulate</value>
              </list>
  </property>
</bean>

   凡是方法名匹配value中字符串,使用advice为XXInterceptor实现拦截。

正则表达式切入法另外一个案例:

正则表达式中匹配规则:

动态切入面pointcuts

  • 需要在运行时进行动态切入。
  • 提供ControlFlowPointcut,这个pointcut将基于线程的调用栈Stack信息
  • 如果发现一个类或方法被当前Stack调用,就被拦截执行切入。

案例代码:

 

 

下页

Spring专题