AOP之Pointcut、Advisor
上篇的所定义的Advice都是直接织入至代理接口执行前后的,或者在执行方法过程中出现异常的时候织入。事实上还有更加细致的织入时机。Pointcut定义了感兴趣的Jointpoint(Advice的应用时机)。在spring中,使用PointcutAdvisor提供的Pointcut实例,具体结合Advice,Spring内建的Pointcut都有对应的PointcutAdvisor。
官方文档解释:在Spring里,一个advisor是一个仅仅包含一个通知对象和与之关联的切入点表达式的切面。
除了引入这种特殊形式,任何advisor都可以和任何通知一起工作。 org.springframework.aop.support.DefaultPointcutAdvisor是最常用的advisor类。
例如,它可以和: MethodInterceptor,BeforeAdvice 或者 ThrowsAdvice一起使用。
在Spring里有可能在同一个AOP代理里模糊advisor和通知类型。
例如,你可以在一个代理配置里使用一个interception环绕通知,一个异常通知和一个前置通知:Spring将负责自动创建所需的拦截器链。
我的通俗解释:就是将一个advice和对应不同的规则进行匹配,就是将advice给包装升级了,使用的时候和advice一样使用
1、NameMatchMethodPointcoutAdvisor(这里是一个织入时机的更加细致的处理,通过名字来对应,这样很明显的一个好处就是,我可以针对要代理类中的部分方法进行织入,而不是每个方法都进行织入)
<bean id="beforeAdvice" class="com.itcast.advice.LogBeforeAdvice"></bean> <bean id="afterAdvice" class="com.itcast.advice.LogAfterAdvice"></bean> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="helloSpeaker"></property> <property name="interceptorNames"> <list> <value>helloAdvise</value> </list> </property> </bean> <!--helloAdvise的名字匹配的方式来匹配要进行advice处理的方法--> <bean id="helloAdvise" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedName" value="hello*"></property> <property name="advice" ref="beforeAdvice"></property> </bean>
或者还可以定义成如下方式:
<!--helloAdvise直接指定要引入的advice方法的那些类文件中的具体方法列表--> <bean id="helloAdvise" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor"> <property name="mappedNames" > <list> <value>helloAaa</value> <value>helloBbb</value> </list> </property> <property name="advice" ref="beforeAdvice"></property> </bean>
2、RegExpMethodPointcutAdvisor(这里是通过正则表达式来编写Pointcut的表示式)
定义的时候可以使用的符号:
. 符合任何单一字符
+ 符合前一个字符一次或者多次
* 符合前一个字符零次或者多次
\ Escape任何Regular expression使用到的符号
写法例如:
<bean id="beforeAdvice" class="com.itcast.advice.LogBeforeAdvice"></bean> <bean id="afterAdvice" class="com.itcast.advice.LogAfterAdvice"></bean> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="target" ref="helloSpeaker"></property> <property name="interceptorNames"> <list> <value>regAdvise</value> </list> </property> </bean> <bean id="regAdvise" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice" ref="afterAdvice"></property> <property name="pattern" value=".*Bbb"></property> </bean>
这里是根据正则表达式来完成对于相关要进行advisor的方法。
总结一下:上边的几种方式的目的都是一样的就是为了给我们定义的代理类更加方便增加advice方法。手段无外乎就似乎用正则表达式、名字匹配的方法。总之就是灵活的配置,最后选择哪种,看你的具体需求。
上边涉及的核心类文件不再重复贴出,只贴出调用验证的类:(这里只是需要获取helloProxy这个代理bean,调用他的方法看效果就ok了)
package com.itcast.aop.xml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.itcast.proxy.IHello; public class SpringAopMain { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("bean-config.xml"); /**测试advise的使用*/ IHello hello =(IHello)ctx.getBean("helloProxy"); hello.hiAAA("测试aaa"); } }
有兴趣的可以根据上边的配置文件完成不同种类的声明方式进行组合测试。
本篇的核心点就是配置文件上的声明,配置文件上的各种声明方式,帮我们给被代理的bean赋予了不同的advice、advisor。