第一步,创建通知。Spring中定义的五种形式的通知,分别是before、after-returning、after-throwing、around和introduction。我们可以定义一个通知类实现上述五种形式中的一种或几种。
第二步,定义切点和通知者。切点是一个或多个应该被切面使用的连接点。意在告诉程序在哪里使用第一步中创建的通知。Spring提供了正则表达式切点和AspectJ表达式切点:(org.springframework.aop.support.JdkRegexpMethodPointcut,org.springframework.aop.aspectj.AspectJExpressionPointcut)。然后将切点和通知关联到通知者。
<bean id="audienceAdvice" class="org.springsource.springidol.AudienceAdvice"> //AudienceAdvice为实现了五种通知接口中的某些接口的类 <property name="audience" ref="audience" /> </bean> <bean id="pointcut" class="*.JdkRegexpMethodPointcut"> <property name="pattern" value=".*perform"/> </bean> <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor"> <property name="advice" ref="audienceAdvice"/> <property name="pointcut" ref="performancePointCut"/> </bean>
当然也有一些更为简洁的方法,不在本文的论述范围,本文是为了说明创建切面的过程。
第三步,最后定义代理类来代理目标bean的功能。
<bean id="jugglerProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="juggler"/> <property name="interceptorNames" value="audiencePointcutAdvisor"/> <property name="proxyInterfaces" value="org.springsource.springidol.Performer"/> </bean>
当我们调用一个被通知的Bean上的方法是,首先调用的是代理上的方法,然后代理会使用切点来决定通知是否应该被应用,最后调用被通知的bean本省。
其中PoxyFactoryBean代理了juggler Bean的一些操作,interceptorNames则是说audiencePointcutAdvisor这个通知被用于bean juggler,而proxyInterfaces则告诉ProxyFactoryBean动态代理需要实现Performer接口(因为bean juggler实现了Performer接口,而通知是在切点perform()方法前后执行)。
ps:利用aop元素进行配置可以对配置文件进行精简,<aop:config>可以申明对什么样的bean的什么方法启用通知者,
<aop:config> <aop:aspect ref="paula"> <aop:before pointcut="execution(* *.perform(..))" method="greetPerformer"/> <aop:after-returning pointcut="execution(* *.perform(..))" method="saySomethingNice"/> <aop:after-throwing pointcut="execution(* *.perform(..))" method="saySomethingNiceAnyway"/> </aop:aspect> </aop:config>
(不需要在代码中增加标注)
还有一种方式是使用@Aspect标注,只需在配置文件中添加:
<aop:aspectj-autoproxy />,然后再代码中编写标注。