`

应用Spring AOP(二)-------通过Advisor指定切入点

阅读更多

       上一篇日志使用的前置通知,后置通知,环绕通知和异常通知可以很好的拦截方法,并插入相应的代码。但是却存在一个问题,就是Spring AOP拦截了目标类中的所有方法。而在通常情况下,只需要拦截部分方法,比如只需要拦截目标类中方法名以set开始的所有方法。Spring AOP提供了Advisor和PointcutAdvisor来达到这个目的。

       常用的PointAdvisor有三种,DefaultPointcutAdvisor , RegexpMethodPointcutAdvisor 和 NameMatchMethodPointcutAdvisor,它们都在org.springframework.aop.support包中。由它们的名字可以看出,RegexpMethodPointcutAdvisor是通过正则表达式来匹配拦截的方法,NameMatchMethodPointcutAdvisor通过直接指定那些方法是需要拦截的,它也可以用*作为通配符。DefaultPointcutAdvisor则需要自定义切入点类。

       在上一篇日志的工程基础上的示例工程代码:

 结构没多少差别,就是com.aop包中多了一个MyPointcut类。当然applicationContext.xml文件内容也变化了,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	
	<bean id="myUserService" class="com.service.UserService"></bean>
	
	<!-- 定义前置通知 -->
    <bean id="beforeLogAdvice" class="com.aop.BeforeLogAdvice"></bean>
    <bean id="beforePointcut" class="com.aop.MyPointcut"></bean>
    <bean id="myAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
      <property name="pointcut">
          <ref local="beforePointcut"/>
      </property>
      <property name="advice">
          <ref local="beforeLogAdvice"/>
      </property>
    </bean>
    
    <!-- 定义后置通知 -->
	<bean id="afterLogAdvice" class="com.aop.AfterLogAdvice"></bean>
	<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
      <property name="patterns">
         <list>
           <value>.*deleteUser</value>
         </list>
      </property>
      <property name="advice">
          <ref local="afterLogAdvice"/>
      </property>
    </bean>
	
	<!-- 定义环绕通知 -->
	<bean id="logAroundAdvice" class="com.aop.LogAroundAdvice"></bean>
    <bean id="myAroundAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">  
      <property name="mappedNames">
        <list>
          <value>*User</value>
        </list>
      </property>
      <property name="advice">
        <ref local="logAroundAdvice" />
      </property>
    </bean>
	
	<!-- 定义异常通知 -->
	<bean id="throwsLogAdvice" class="com.aop.ThrowsLogAdvice"></bean>
    
	
    <!-- 定义代理类,名 称为myProxy,将通过myProxy访问业务类中的方法 -->
	<bean id="myProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
	  <property name="proxyInterfaces">
	    <value>com.service.IUserService</value>
	  </property>
	  <property name="interceptorNames">
	    <list>	     
	     <value>myAdvisor</value>
	     
	     <value>regexpAdvisor</value>
	     
	     <value>myAroundAdvisor</value>
	     
	     <value>throwsLogAdvice</value>
	    </list>
	  </property>
	  <property name="target" ref="myUserService"></property>
	</bean>
</beans>

对比上一个工程applicationContext.xml文件的内容,id为myProxy的bean里的interceptorNames拦截器名的list下不再是四个通知了。前置通知,后置通知和环绕通知都变成了Advisor。下面挨个来看。

 

首先看前置通知:

<!-- 定义前置通知 -->
    <bean id="beforeLogAdvice" class="com.aop.BeforeLogAdvice"></bean>
    <bean id="beforePointcut" class="com.aop.MyPointcut"></bean>
    <bean id="myAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
      <property name="pointcut">
          <ref local="beforePointcut"/>
      </property>
      <property name="advice">
          <ref local="beforeLogAdvice"/>
      </property>
    </bean>

 这里自定义了一个MyPointcut切入点类:

package com.aop;

import java.lang.reflect.Method;

import org.springframework.aop.support.NameMatchMethodPointcut;

public class MyPointcut extends NameMatchMethodPointcut {

	public boolean matches(Method method, Class targetClass) {
		this.setMappedName("addUser");
		//this.setMappedName("*User");
		return super.matches(method, targetClass);
	}
}

        Spring AOP在调动目标类的每一个方法之前,都会调用这里的matches方法来判断是否应该拦截该方法,当matches方法返回true时,表明当前方法应该被拦截。如果要想指定被拦截的方法,需要调用NameMatchMethodPointcut的setMappedName方法。本例中指定了addUser方法。当然也可以使用*作为通配符。如代码中的注释,this.setMappedName("*User")将会拦截以User结尾的所有方法。

        要想使用自定义的这个Pointcut类,必须装配DefaultPointcutAdvisor,即applicationContext.xml中id为myAdvisor的bean。这个bean中的pointcut属性指定了切入点,advice属性指定了通知。

 

再来看看后置通知:

<!-- 定义后置通知 -->
	<bean id="afterLogAdvice" class="com.aop.AfterLogAdvice"></bean>
	<bean id="regexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
      <property name="patterns">
         <list>
           <value>.*deleteUser</value>
         </list>
      </property>
      <property name="advice">
          <ref local="afterLogAdvice"/>
      </property>
    </bean>

 这里用到了RegexpMethodPointcutAdvisor。bean下的patterns属性下添加一些正则表达式规则,能够匹配这些规则的方法就会被拦截。值得一提的是,这儿匹配的是方法的完整路径,包括类名已经类的包名。回顾一下,这儿的目标类是com.service.UserService,它里面只有两个方法addUser和deleteUser。这两个方法的完整路径就是com.service.UserService.addUser 和  com.service.UserService.deleteUser 。这儿写的正则表达式是.*deleteUser ,明显它可以匹配com.service.UserService.deleteUser,所以这个方法会被拦截。假设将正则表达式写成deleteUser,那么它不能匹配com.service.UserService.deleteUser 这整个字符串,所以讲不会起作用。如果要拦截方法名中包含abc的方面,正则表达式写成.*abc.*就可以了(当然包名和类名不能是abc啦)。

 

最后看看环绕通知:

<!-- 定义环绕通知 -->
	<bean id="logAroundAdvice" class="com.aop.LogAroundAdvice"></bean>
    <bean id="myAroundAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">  
      <property name="mappedNames">
        <list>
          <value>*User</value>
        </list>
      </property>
      <property name="advice">
        <ref local="logAroundAdvice" />
      </property>
    </bean>

 这里用到了NameMatchMethodPointcutAdvisor,它的mappedNames属性下添加想要拦截的方法名就可以了,当然也可以用*通配符啦,*User就代表所有以User结尾的方法。注意这儿只匹配方法名,不会管类名和包名了。

 

工程代码在附件中。。。。

  • 大小: 15.6 KB
分享到:
评论

相关推荐

    Spring-Reference_zh_CN(Spring中文参考手册)

    切入点指定者的支持 6.2.3.2. 合并切入点表达式 6.2.3.3. 共享常见的切入点(pointcut)定义 6.2.3.4. 示例 6.2.4. 声明通知 6.2.4.1. 前置通知(Before advice) 6.2.4.2. 返回后通知(After returning advice) ...

    spring代码课堂笔记

    可以动态的将切面指定对应切入点 Spring AOP Advisor继承实现关系 Advisor PointCutAdvisor:可以灵活的指定当前接口下的哪一个实现类中哪一个方法与次要业务 进行绑定 Advice PointCut (次要业务) (目标...

    spring chm文档

    7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的基类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 ...

    spring.net中文手册在线版

    使用切入点-基本概念 26.3.深入探讨 26.3.1.其它类型的通知 26.3.1.1.前置通知 26.3.1.2.后置通知 26.3.1.3.异常通知 26.3.1.4.引入(mixins) 26.3.1.5.通知链 26.3.1.6.配置通知 26.3.2.使用特性定义切入点 26.4....

    spring源码详解

    (4)切入点 (Pointcut) 指定哪些连接点可以应用切面/通知 (5)目标对象(target) 就是被代理的对象,也就是具体的业务逻辑。比如OrderService (6)代理对象(proxy) 将切面代码织入到目标对象之后的...

    Spring中文帮助文档

    7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的超类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 ...

    Spring 2.0 开发参考手册

    7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的基类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 ...

    Spring API

    7.2. Spring中的切入点API 7.2.1. 概念 7.2.2. 切入点运算 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.5. 切入点的超类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 ...

    spring in action英文版

     3.3.3 使用Spring的静态切入点  3.3.4 使用动态切入点  3.3.5 切入点实施  3.4 创建引入  3.4.1 实现IntroductionInterceptor  3.4.2 创建一个引入Advisor  3.4.3 谨慎使用引入通知  3.5 ...

    SSH第7章上机.zip ACCP8.0

    -- 将事务管理规则的切面应用到对应的切入点 --&gt; &lt;aop:config&gt; &lt;aop:pointcut expression="execution(* com.direct.service.*.*(..))" id="transactionPointCut"/&gt; &lt;aop:advisor advice-ref="transactionAdvice...

    Maven拆分代码.zip

    --aop面向切面编程,切面就是切入点和通知的组合--&gt; &lt;!--配置事务管理器--&gt; &lt;bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"&gt; &lt;!--配置事务的通知...

Global site tag (gtag.js) - Google Analytics