AOP的目的就是要把共通的切面(Aspect)抽出来,允许不同的对象复用。比如打日志,记录方法执行时间等。
于是一个Aspect的实例(advisor),需要表达清楚两点:
1.pointCut,即准入条件。类名和方法名符合什么样的要求,才可以触发切面执行。如方法签名具有annotation @Monitor。
2.advice,即触发的动作。一般会在如下几种时机触发:方法执行before、after、around、throw exception、finally。如方法执行完毕(finally)记录日志:“XX类的XX方法被执行!”
一个典型且原始的AOP配置如下所示:
<bean id="personTarget" class="com.mycompany.PersonImpl">
<property name="name"><value>Tony</value></property>
<property name="age"><value>51</value></property>
</bean>
<bean id="myAdvisor" class="com.mycompany.MyAdvisor">
<property name="someProperty"><value>Custom string property value</value></property>
</bean>
<bean id="debugInterceptor" class="org.springframework.aop.interceptor.NopInterceptor">
</bean>
<bean id="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces"><value>com.mycompany.Person</value></property>
<property name="target"><ref local="personTarget"/></property>
<property name="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
代理类person将最终暴露给外部使用,其target属性指向真正的业务对象。通过代理模式,使得调用方法前后,被代理对象能够执行新的功能、获得新的特性。
interceptorNames属性列举了代理类需要叠加的切面实例(advisor),每个实例各自表达准入条件和触发的动作。
后来,我们有了AspectJ,对下述两个方面做了优化:
1、每个需要代理的对象都要通过ProxyFactoryBean配置一把,导致配置繁琐、冗长。引入auto-proxy。
2、准入条件的描述不再需要逐个用java实现,改为expression。
一个典型的AspectJ风格的切面Advisor如下所示:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class BeforeExample {
@Before("execution(* com.xyz.someapp.dao.*.*(..))")
public void doAccessCheck() {
// ...
}
}
@Before表示时机,后面的表达式表示准入条件pointCut,方法实现即待触发的动作advice。
三个要素共同构成了一个Advisor。
通过添加配置
<aop:aspectj-autoproxy/>
只要像配置普通bean那样配置了BeforeExample,即可对所有满足条件的类产生代理。上例中即所有com.xyz.someapp.dao.*包下的类。
参考:
http://blog.csdn.net/sarkuya/article/details/3862987
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html