上一篇博客是介绍了通知,但是通知有很大的缺陷,那就是在我们把通知织入到目标方法的时候,只能将切面织入到目标类的所有方法中,不能指定目标类中具体的方法。
顾问是另一种切面,它可以完成更加复杂的功能。它可以指定具体的切入点。PointcutAdvisor是顾问的一种,可以制定具体的切入点。这个接口有两个常见的实现类:
- NameMatchMethodPointcutAdvisor:名称匹配方法切入点顾问
- RegexpMethodPointcutAdvisor:正则表达式匹配方法切入点顾问
下面看看这两个顾问如何·实现织入的。
一、NameMatchMethodPointcutAdvisor
他的意思是容器可以根据配置文件中指定的方法名来设置切入点。下面直接通过代码看看这个顾问怎么配置:
1、定义接口
//主目标接口
public interface ISomeService {
//目标方法
String doFirst();
void doSecond();
void doThird();
}
2、定义接口实现类
public class SomeServiceImpl implements ISomeService {
public String doFirst() {
System.out.println("doFirst");
return "abcde";
}
public void doSecond() {
System.out.println("doSecond");
}
@Override
public void doThird() {
System.out.println("doThird");
}
}
3、定义通知
//后置通知:可以获取到目标方法的返回结果,但是无法改变其值
public class MyAfterReturningAdvice implements AfterReturningAdvice {
//在目标方法执行之后
//returnValue:目标方法的返回值
public void afterReturning(Object returnValue, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("后置通知内部获取参数值:returnValue:"+returnValue);
}
}
4、配置文件applicationConetext.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"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 注册 目标对象-->
<bean id="someService" class="com.fdd.aop09.SomeServiceImpl">
</bean>
<!-- 注册切面:通知 -->
<bean id="myAdvice" class="com.fdd.aop09.MyAfterReturningAdvice">
</bean>
<!-- 切面注册:顾问,用于指定目标类的切入点 -->
<bean id="myAdvisor" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="myAdvice"></property>
<!-- 指定切入点 -->
<property name="mappedName" value="doFirst"></property>
<!-- 指定多个切入点的方式 -->
<!-- <property name="mappedNames" value="doFirst,doThird"></property> -->
</bean>
<!-- 生成代理对象 -->
<bean id="serviceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 制定目标对象 -->
<!-- <property name="targetName" value="someService"></property> -->
<property name="target" ref="someService"></property>
<!-- 指定顾问 -->
<property name="interceptorNames" value="myAdvisor"></property>
</bean>
</beans>
从上面可以看到,我们在注册通知的时候没有指定哪一个目标对象,而是在顾问中声明,并把要增强的切入点名称指定,最后通过代理,将目标类和顾问链接起来,此时容器就会寻找目标类中的切入点,看看哪一个满足条件。
5、测试
@Test
public void test01(){
String resource = "com/fdd/aop09/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
ISomeService service =(ISomeService) ac.getBean("serviceProxy");
service.doFirst();
System.out.println("=====");
service.doSecond();
System.out.println("=====");
service.doThird();
}
看结果:
我们可以看到在这里只对doFirst方法进行增强。
二、RegexpMethodPointcutAdvisor
RegexpMethodPointcutAdvisor也就是正则表达式方法顾问,容器可以根据正则表达式来设置切入点。但是此时与正则表达式进行匹配的是接口中的方法名,不是目标类中的方法名
这里面使用了正则表达式,在网上一查一大堆。
最后验证,代码和结果跟上面一样,不说了