上一篇日志使用的前置通知,后置通知,环绕通知和异常通知可以很好的拦截方法,并插入相应的代码。但是却存在一个问题,就是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结尾的方法。注意这儿只匹配方法名,不会管类名和包名了。
工程代码在附件中。。。。
相关推荐
1. Advisor接口:Advisor是AOP的核心概念,它封装了Pointcut(切入点)和Advice(通知)。一个Advisor可以识别何时应用特定的Advice,并决定在何处应用。 2. Pointcut接口:Pointcut是程序执行中的一个特定点,如...
- 在`<aop:config>`标签内定义切面,`<aop:pointcut>`定义切入点,`<aop:advisor>`定义通知。 - `<aop:aspect>`标签用于定义完整的切面,包括切入点和通知。 - **注解配置**: - 使用`@Aspect`注解定义切面类,`...
1. **基于XML的配置**:通过在Spring配置文件中声明切面、切入点和通知来实现。 2. **基于注解的方式**:使用`@AspectJ`风格的注解来声明切面和通知。 #### 四、Spring AOP 的配置示例 下面是一个简单的基于注解的...
使用Spring AOP,开发者可以定义切面,声明切入点(即关注点的定位),编写通知(即实际的增强代码),并通过配置将它们应用到目标对象上。这样,我们可以保持业务逻辑的清晰,同时实现系统级的服务,如事务管理、...
在 `inactive-aop.xml` 配置文件中,我们可以通过 `<aop:config>` 和 `<aop:advisor>` 标签来声明和配置这个 Advisor,指定其切入点表达式。 总的来说,Spring AOP 拦截器 Advisor 是一种强大的工具,它允许我们在...
- **`org.springframework.aop.aspectj.AspectJExpressionPointcut`**:实现切入点表达式的解析和匹配。 - **`org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAdvisorFactory`**:处理基于...
在Spring的XML配置文件中,可以通过`<aop:config>`元素开启AOP,并通过`<aop:pointcut>`定义切入点,`<aop:advisor>`或`<aop:aspect>`定义切面。此外,还可以使用注解方式来声明切点和切面,如`@Aspect`、`@Pointcut...
- `<aop:advisor>`:定义通知和切入点的关联,指定何时何地执行通知。 - `<aop:aspect>`:定义切面,包括其通知和切入点。 - `<aop:before>`、`<aop:after>`、`<aop:around>`等:分别用于定义不同类型的通知。 **5....
4. **切入点(Pointcut)**:定义一组连接点的表达式,用于指定通知何时应用。 5. **织入(Weaving)**:将切面应用到目标对象以创建新的代理对象的过程,可以在编译时、类加载时或运行时进行。 ### 三、Spring AOP...
- **增强器/切面封装(Advisor)**:封装了切入点和通知,是Spring AOP中的基本单位。 - **ProxyFactoryBean**:Spring AOP中的代理工厂Bean,用于创建代理对象。 #### 六、实战示例:模拟Warcraft游戏 - **示例简介*...
切入点是一组连接点的总称,用于指定某个增强应该在何时被调用。 增强是指在特定连接点执行的动作。许多 AOP 框架都以拦截器的形式来表现增强--所谓拦截器是这样的一个对象:当连接点被调用时,它会收到一个回调...
- XML配置:在Spring配置文件中定义切面、通知和切入点。 - 注解配置:使用`@EnableAspectJAutoProxy`开启基于注解的AOP支持,并在类上使用`@Aspect`定义切面。 - 自动代理:Spring会根据配置自动生成代理对象,...
Advisor通常包含一个Pointcut(切入点)和一个对应的Advice。 在实际开发中,aopalliance-1.0.jar常作为Spring框架的一部分使用,因为Spring AOP就是基于AOP Alliance的接口实现的。Spring框架通过使用AOP Alliance...
在实际应用中,我们会在`<bean>`元素中定义切面类,并在`<aop:config>`中通过`<aop:aspect>`元素引用它,然后定义相应的通知和切入点。例如: ```xml <aop:config> <aop:aspect id="loggingAspect" ref="logging...
3. **基于XML配置的AOP**:在Spring的配置文件中,可以通过`<aop:config>`、`<aop:advisor>`、`<aop:pointcut>`等标签定义切面、通知和切入点。 ### 三、Spring AOP实战 1. **经典代理模式**:通过JDK动态代理或...
- **切点(Pointcut)**:定义了通知应该在哪些方法上应用,可以通过切入点表达式来指定,如`execution(* com.example.service.*.*(..))`表示匹配com.example.service包下的所有方法。 - **通知(Advice)**:在切点...
- 这个例子展示了如何定义一个事务顾问`txAdvice`,并通过`<aop:advisor>`标签将其与切入点`busServiceMethods`关联起来。这表示所有符合该切入点定义的方法调用都将受到事务控制。 #### 四、Aspect与Advisor之间...