1、后置通知
当需要在街口方法调用后统一处理事务,如关闭资源,可以使用后置通知。Spring中的后置通知(After Returning advice)必须实现 org.springframework.aop.AfterReturningAdvice 接口,如下:
public class MyAfterReturningAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object tagert) throws Throwable {
// TODO Auto-generated method stub
System.out.println("close resource");
}
}
2、环绕通知
当需要在调用接口方法前和调用方法后统一处理事务,可以使用环绕通知。实现环绕通知的MethodInterceptor应当实现下面的接口:
package com.mdd.aop;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
// TODO Auto-generated method stub
System.out.println("调用方法前执行");
Object obj= arg0.proceed();
System.out.println("调用方法后执行");
return obj ;
}
}
该接口同前两种通知有两个重要区别:1.该通知能够控制目标方法是否真的被调用。通过invocation.proceed()方法来调用。
该通知可以控制返回的对象。可以返回一个与proceed()方法返回对象完全不同的对象。但要谨慎使用。
3、异常通知
当目标对象的方法出现异常,会统一在异常通知处理。如果连接点抛出异常,异常通知(throws advice)将在连接点返回后被调用。
package com.mdd.aop;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdvice implements ThrowsAdvice {
public void afterThrowing(Method m, Object[] os, Object
target, Exception e)
{
System.out.println("出大事了"+ e.getMessage());
}
}
4、引入通知
若只需要目标对象指定的方法织入特定的通知,而不是所有的方法,则需要配置引入通知。通过org.springframework.aop.support.NameMatchMethodPointcutAdvisor来进行配置引入通知。
5、各种通知的配置
接口1:Test2ServiceInter.java
package com.mdd.aop;
public interface Test2ServiceInter {
public void sayBye();
}
package com.mdd.aop;
public interface TestServiceInter {
public void sayHello();
}
package com.mdd.aop;
public class Test1Service implements TestServiceInter, Test2ServiceInter{
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
private int age;
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("Hello "+userName +"Age " +age);
// int i = 9/0;
// System.out.println(i);
}
@Override
public void sayBye() {
// TODO Auto-generated method stub
System.out.println("ByeBye "+userName +"Age " +age);
}
}
通知的配置如下:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<bean id="test1Service" class="com.mdd.aop.Test1Service">
<property name="userName">
<value>madingding</value>
</property>
<property name="age" value="25"/>
</bean>
<bean id="myAfterReturningAdvice" class="com.mdd.aop.MyAfterReturningAdvice"/>
<!--配置环绕通知 -->
<bean id="myMethodInterceptor" class="com.mdd.aop.MyMethodInterceptor"/>
<bean id ="myThrowsAdvice" class="com.mdd.aop.MyThrowsAdvice"/>
<!--定义后置通知的切入点 -->
<!--定义只对代理接口的sayHello方法织入后置通知,其他方法不会有后置通知 -->
<bean id="myMethodAfterAdviceFilter" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="advice" ref="myAfterReturningAdvice"/>
<property name="mappedNames">
<list>
<value>sayHello</value>
</list>
</property>
</bean>
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--代理接口集 -->
<property name="proxyInterfaces">
<list>
<value>com.mdd.aop.TestServiceInter</value>
<value>com.mdd.aop.Test2ServiceInter</value>
</list>
</property>
<!-- 将通知织入到代理对象 -->
<property name="interceptorNames">
<!-- 植入后置通知 -->
<list>
<value>myThrowsAdvice</value>
<!--使用自定义切入点来控制后置通知 ,通过引入通知来控制某个方法织入的通知 -->
<value>myMethodAfterAdviceFilter</value>
<value>myMethodInterceptor</value>
</list>
</property>
<!-- 配置被代理对象 -->
<property name="target" ref="test1Service"/>
</bean>
</beans>
执行结果如下,从结果可以看出,通过引入通知过滤之后,只有sayHello方法织入了后置通知,其他方法没有后置通知。
调用方法前执行
Hello madingdingAge 25
调用方法后执行
close resource
*********************
调用方法前执行
ByeBye madingdingAge 25
调用方法后执行