Spring AOP
版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://blackanger.blog.51cto.com/140924/22425 |
引自友人blog: http://blog.csdn.net/senton
一。创建切面:
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 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <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文件稍加改动即可,意思和上面的差不多,这里就不多加注释了。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <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; } } 2.把上面的XMl文件稍加改动即可,意思和上面的差不多,这里就不多加注释了。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <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() + " 异常!"); } } 2.xml文件。把上面的稍加修改: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <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被执行后,原来的异常继续被抛出,并且象其他异常一样被传播出去。 本文出自 “{ :Alex Space => " Ruby Notes " }” 博客,请务必保留此出处http://blackanger.blog.51cto.com/140924/22425 本文出自 51CTO.COM技术博客 |



blackanger
博客统计信息
热门文章
最新评论
友情链接
