一。建立切面:
Spring中的通知類型有四種:
Around:攔截對目標對象方法調用,
Before:在目標方法被調用以前調用,
After:在目標方法被調用以後調用,
Throws:當目標方法拋出異常時調用。
1)下面是一個Before類型的簡單例子。
1.首先建立一個攔截的類:
package cn.itcast;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.MethodBeforeAdvice;
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {//實現MethodBeforeAdvice接口
Log log = LogFactory.getLog(this.getClass());
public MyMethodBeforeAdvice() {
super();
}
public void before(Method arg0, Object[] arg1, Object arg2)//實現MethodBeforeAdvice接口的before方法,
throws Throwable {
StringBuilder sb = new StringBuilder();
if (arg1 == null) {
sb = new StringBuilder("無參數!");
} else {
for (int i = 0; i < arg1.length; i++) {
if (i != arg1.length - 1) {
sb.append(arg1[i] + ",");
} else {
sb.append(arg1[i]);
}
}
}
log.info("類名: " + arg2.getClass().getName() + " 方法名: "
+ arg0.getName() + " 參數:" + sb.toString());
}
}
這個類中咱們沒作太多的事,就是把方法名等信息打印出來而已,固然你能夠根據業務需求作其餘的不少事情。
2.
寫一個配置文件:applicationContext.xml
<beans>
<bean id="myArrayList" class="java.util.ArrayList" />
<bean id="myMethodBeforeAdvice" class="cn.itcast.MyMethodBeforeAdvice" />
<bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<!--指定攔截類的名字,能夠加入多個,它會去檢查此類實現的是什麼接口,而後去調用裏面相應的方法-->
<list>
<value>myMethodBeforeAdvice</value>
</list>
</property>
<property name="target"><!--指定目標對象-->
<ref bean="myArrayList" />
</property>
<property name="proxyInterfaces">
<!--指定目標對象實現的接口,也能夠是多個-->
<list>
<value>java.util.Collection</value>
</list>
</property>
</bean>
</beans>
3.再寫一個測試類
package cn.itcast.test;
import java.util.Collection;
import junit.framework.TestCase;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestMySpringAop extends TestCase {
ApplicationContext applicationContext = null;
Collection collection = null;
protected void setUp() throws Exception {
super.setUp();
applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
}
public void testMySpring() {
collection = (Collection) applicationContext.getBean("collection");
collection.add("zhangsan");
assertEquals(1, collection.size());
}
}
運行!結果爲:
類名: java.util.ArrayList 方法名: add 參數:zhangsan
類名: java.util.ArrayList 方法名: size 參數:無參數!
看....簡單吧?!
2) 再來一個After的例子。
1.首先建立一個攔截的類:
package cn.itcast;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.AfterReturningAdvice;
public class MyAfterReturningAdvice implements AfterReturningAdvice {
Log log = LogFactory.getLog(this.getClass());
public MyAfterReturningAdvice() {
super();
}
public void afterReturning(Object arg0, Method arg1, Object[] arg2,
Object arg3) throws Throwable {
StringBuilder sb = new StringBuilder();
if (arg2 == null) {
sb = new StringBuilder("無參數!");
} else {
for (int i = 0; i < arg2.length; i++) {
if (i != arg2.length - 1) {
sb.append(arg2[i] + ",");
} else {
sb.append(arg2[i]);
}
}
}
log.info("返回值: " + arg0.toString() + " 類名: "
+ arg3.getClass().getName() + " 方法名: " + arg1.getName()
+ " 參數:" + sb.toString());
}
}
2.把上面的XMl文件稍加改動便可,意思和上面的差很少,這裏就很少加註釋了。
<beans>
<bean id="myArrayList" class="java.util.ArrayList" />
<bean id="myAfterReturningAdvice" class="cn.itcast.MyAfterReturningAdvice" />
<bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<value>myAfterReturningAdvice</value>
</property>
<property name="target">
<ref bean="myArrayList" />
</property>
<property name="proxyInterfaces">
<value>java.util.Collection</value>
</property>
</bean>
</beans>
3.測試類依然用上面那個。
運行!結果爲:
返回值的類型: true 類名: java.util.ArrayList 方法名: add 參數:zhangsan
返回值的類型: 1 類名: java.util.ArrayList 方法名: size 參數:無參數!
看......如今返回值也取出來了.........
3) 再來看一個Around的例子。步驟和上面同樣,
1.首先也是建立一個攔截的類:
package cn.itcast;
import java.lang.reflect.Method;
import java.util.ArrayList;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class MyMethodInterceptor implements MethodInterceptor {
public MyMethodInterceptor() {
super();
}
Log log = LogFactory.getLog(this.getClass());
public Object invoke(MethodInvocation arg0) throws Throwable {
Object[] arguments = arg0.getArguments();
Method method = arg0.getMethod();
Object objName = arg0.getThis();
StringBuilder sb = new StringBuilder();
if (arguments == null) {
sb = new StringBuilder("無參數!");
} else {
for (int i = 0; i < arguments.length; i++) {
if (i != arguments.length - 1) {
sb.append(arguments[i] + ",");
} else {
sb.append(arguments[i]);
}
}
}
//在調用目標方法以前作的事
log.info("類名: " + objName.getClass().getName() + " 方法名: " + method.getName()
+ " 參數:" + sb.toString());
Object object = arg0.proceed();//經過調用此方法來調用目標方法。
//在調用目標方法以後作的事
if(objName instanceof ArrayList){
ArrayList arrayList = (ArrayList) objName;
arrayList.add("lisi");
arrayList.add("wangwu");
log.info("size = " + arrayList.size());
}
return object;
}
}
<beans>
<bean id="myArrayList" class="java.util.ArrayList" />
<bean id="myMethodInterceptor" class="cn.itcast.MyMethodInterceptor" />
<bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<value>myMethodInterceptor</value>
</property>
<property name="target">
<ref bean="myArrayList" />
</property>
<property name="proxyInterfaces">
<value>java.util.Collection</value>
</property>
</bean>
</beans>
3.運行!結果:
類名: java.util.ArrayList 方法名: add 參數:zhangsan
size = 3
類名: java.util.ArrayList 方法名: size 參數:無參數!
size = 5
咱們類分析一下運行的結果。在測試類中調用了一次目標類的add方法,此時size爲1,而後在攔截類裏面把對象取出來調用了兩次add方法,這時size爲3,也就是咱們看到的第一個size,接着在測試類中調用了一次size方法,此時它又被攔截了,因此再一次調用了兩個add方法,最後的size固然就是5了。固然若是咱們這裏用的是Set集合就不會再add後面的兩個已存在的對象了。
4)一個ThrowsAdvice的例子。步驟和上面同樣,
1.寫一個攔截異常的類。這裏面能夠有多個帶不一樣異常參數類型afterThrowing方法,運行時根據拋出異常的類型去調用恰當的方法,
package cn.itcast;
import java.lang.reflect.Method;
import org.springframework.aop.ThrowsAdvice;
public class MyThrowsAdvice implements ThrowsAdvice {
public MyThrowsAdvice() {
super();
// TODO Auto-generated constructor stub
}
public void afterThrowing(Method method, Object[] args, Object target,
NullPointerException npe) {
System.out.println("調用 " + target.getClass().getName() + " 的 "
+ method.getName() + " 方法時發生了 " + npe.getClass().getName()
+ " 異常!");
}
}
<beans>
<bean id="myArrayList" class="java.util.ArrayList" />
<bean id="myMethodBeforeAdvice" class="cn.itcast.MyMethodBeforeAdvice" />
<bean id="myAfterReturningAdvice" class="cn.itcast.MyAfterReturningAdvice" />
<bean id="myMethodInterceptor" class="cn.itcast.MyMethodInterceptor" />
<bean id="myThrowsAdvice" class="cn.itcast.MyThrowsAdvice" />
<bean id="collection" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interceptorNames">
<value>myThrowsAdvice</value>
</property>
<property name="target">
<ref bean="myArrayList" />
</property>
<property name="proxyInterfaces">
<value>java.util.Collection</value>
</property>
</bean>
</beans>
3.寫一個main方法來測試一下:
package cn.itcast;
import java.util.Collection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainClass {
public MainClass() {
super();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext applicationContext = null;
Collection collection = null;
applicationContext = new ClassPathXmlApplicationContext(
"applicationContext.xml");
collection = (Collection) applicationContext.getBean("collection");
collection.add("zhangsan");
Object[] object = null;
collection.toArray(object);//故意來拋出一個異常試試看
}
}
來看看運行結果:
調用 java.util.ArrayList 的 toArray 方法時發生了 java.lang.NullPointerException 異常!
Exception in thread "main" java.lang.NullPointerException
at java.util.ArrayList.toArray(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:181)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:148)
at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:118)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:170)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:176)
at $Proxy0.toArray(Unknown Source)
at cn.itcast.MainClass.main(MainClass.java:29)
看到了嗎?咱們在攔截異常類裏面的打印語句出來了:
調用 java.util.ArrayList 的 toArray 方法時發生了 java.lang.NullPointerException 異常!
固然在這裏你還能夠作不少事情。在本程序裏面僅打印出這條簡單的信息而已。 下面的是系統拋出的。由此能夠看出,若是有異常的話,代理對象捕獲異常而且調用合適的ThrowsAdvice方法。ThrowsAdvice被執行後,原來的異常繼續被拋出,而且象其餘異常同樣被傳播出去。