Aspect Oriented Programming(AOP),即面向切面编程。对所有对象或一类对象编程。 在不增加代码的基础上,还增加新的功能
通知类型
3.1.3 举个栗子
本例中,
HelloServiceInterface
和ByeServiceInterface
,其中类SayingService
实现了这两个接口中的方法。SayingService
的具体对象配置了四种通知(严格说是五种),分别在该对象调用每一个方法时为其执行这几个通知 TestSpring
|---src
|---com.netease
| |---Advice
| |---MyBeforeAdvice (前置通知,实现了接口MethodBeforeAdvice)
| |---MyAfterReturningAdvice (后置通知,实现了接口AfterReturningAdvice)
| |---MyInterceptAdvice (环绕通知,实现了接口MethodInterceptor)
| |---MyThrowableAdvice (异常通知,实现了接口ThrowsAdvice)
| |---Service
| |---ByeServiceInterface.java (包含方法sayBye)
| |---HelloServiceInterface.java (包含方法sayHello)
| |---SayingService.java (实现了以上两个接口)
| |---Test
| |---TestService.java
|---ApplicationContext.xml
External Libraries
|--- spring.jar
|--- common-logging.jar
|--- ...
代码描述
public class TestService {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");
/*注意这里必须获取代理对象!!否则就白配置了*/
/*代理类实际上实现了这个接口,因此可以通过强转得到HelloServiceInterface*/
HelloServiceInterface helloService = (HelloServiceInterface) applicationContext.getBean("proxyFactoryBean");
helloService.sayHello();
/*同理,由于代理类同样实现了ByeServiceInterface接口*/
ByeServiceInterface byeService = (ByeServiceInterface) helloService;
byeService.sayBye();
}
}
配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=....省略>
<!--配置通知-->
<bean id="myBeforeAdvice" class="com.netease.Advice.MyBeforeAdvice"/>
<bean id="myAfterReturningAdvice" class="com.netease.Advice.MyAfterReturningAdvice"/>
<bean id="myInterceptAdvice" class="com.netease.Advice.MyInterceptAdvice"/>
<bean id="myThrowableAdvice" class="com.netease.Advice.MyThrowableAdvice"/>
<!--配置切入点(可选)-->
<!--这里表示将myBeforeAdvice这个通知绑定到sayHello方法,对其他方法失效-->
<bean id="nameMatchMethodPointcutAdvisor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="myBeforeAdvice"/>
<property name="mappedName" value="sayHello"/>
</bean>
<!--配置目标对象-->
<bean id="helloService" class="com.netease.Service.App">
<property name="name">
<value>zhujie</value>
</property>
</bean>
<!--配置代理对象-->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--配置被代理的接口集合,表示该代理对象服务于哪些接口,即需要实现哪几个接口-->
<property name="proxyInterfaces">
<list>
<value>com.netease.Service.HelloServiceInterface</value>
<value>com.netease.Service.ByeServiceInteface</value>
</list>
</property>
<!--配置被代理的通知-->
<property name="interceptorNames">
<list>
<!--<value>myBeforeAdvice</value>-->
<!--注意这里写的是我们配置的切入点id,如果仍然写前置通知的id,则切入点配置就无效了-->
<value>nameMatchMethodPointcutAdvisor</value>
<value>myBeforeAdvice</value>
<value>myAfterReturningAdvice</value>
<value>myInterceptAdvice</value>
<value>myThrowableAdvice</value>
</list>
</property>
<!--配置被代理的对象-->
<!--表示该对象调用方法时会被注入通知-->
<property name="target" ref="helloService"/>
</bean>
</beans>
把adviceBean中的adviceMethod作用到targetMethod方法调用之前
<aop:config>
<aop:aspect ref="adviceBean">
<aop:before
pointcut="execution(* packageName.className.targetMethod(para...))"
method="adviceMethod"/>
</aop:config>
另一种引用切点表达式的方法
<aop:config>
<aop:aspect ref="adviceBean">
<aop:pointcut
id="performance"
experession="execution(* packageName.className.targetMethod(para...))"/>
<aop:before
pointcut-ref="performance"
method="adviceMethod"/>
</aop:config>