文件名称:
spring aop 实现源代码--xml and annotation(带lib包)
开发工具:
文件大小: 4mb
下载次数: 0
上传时间: 2008-09-18
详细说明:
在Spring1.2或之前的版本中,实现AOP的传统方式就是通过实现Spring的AOP API来定义Advice,并设置代理对象。Spring根据Adivce加入到业务流程的时机的不同,提供了四种不同的Advice:Before Advice、After Advice、Around Advice、Throw Advice。 1、Before Advice 顾名思义,Before Advice会在目标对象的方法执行之前被调用,您可以通过实现org.springframework.aop.MethodBeforeAdvice接口来实现Before Advice的逻辑,接口定义如下: java 代码 1. package org.springframework.aop; 2. 3. public interface MethodBeforeAdvice extends BeforeAdvice { 4. void before(Method method, Object[] args, Object target) throws Throwable; 5. } 其中BeforeAdvice继承自Adivce接口,这 两者都是标签接口,并没有定义任何具体的方法。before方法会在目标对象的指定方法执行之前被执行,在before方法种,你可以取得指定方法的Method实例、参数列表和目标对象,在before方法执行完后,目标对象上的方法将会执行,除非在before方法种抛出异常。 下面通过例子来说明Before Advice的使用方法。首先定义目标对象所要实现的接口: java 代码 1. package com.savage.aop 2. 3. public interface MessageSender { 4. void send(String message); 5. } 接着实现MessageSender接口: java 代码 1. package com.savage.aop; 2. 3. public class HttpMessageSender implements MessageSender { 4. public void send(String message) { 5. System.out.println("Send Message[" + message + "] by http."); 6. } 7. } OK,我们的业务代码实现完了,现在如果要在不改变我们的业务代码的前提下,在执行业务代码前要记录一些日志,这时就可以通过实现MethodBeforeAdvice接口来实现,如: java 代码 1. package com.savage.aop; 2. 3. import java.lang.reflect.Method; 4. 5. import org.springframework.aop.framework.MethodBeforeAdvice; 6. 7. public class LogBeforeAdvice implements MethodAdvice { 8. public void before(Method method, Object[] args, Object target) throws Throwable { 9. System.out.println("Log before " + method + " by LogBeforeAdvice."); 10. } 11. } 然后再在XML进行如下定义: xml 代码 1. 2. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. logBeforeAdvice 17.
18. 19. 20. 这样我们就为MessageSender对象指定了Before Advice对象。在这里,我们分别定义了一个MessageSender对象(messageSenderImpl)和一个Before Advice对象(logBeforeAdvice),并定义了一个 org.springframework.aop.framework.ProxyFactoryBean对象(messageSender),FactoryBean或ApplicationContext将使用ProxyFactoryBean来建立代理对象,在这里就是messageSenderImpl建立代理对象。在ProxyFactoryBean的定义中,proxyInterfaces属性指定了要代理的接口;target指定了要建立代理的目标对象;interceptorNames则指定了应用与指定接口上的Advices对象列表,spring将根据列表中定义的顺序在执行目标对象的方法前、后执行Advice中定义的方法。 现在我们写一个程序来验证下: java 代码 1. package com.savage.aop; 2. 3. import org.springframework.context.ApplicationContext; 4. import org.springframework.context.support.ClassPathXmlApplication; 5. 6. public class AdviceDemo { 7. public void main(String[] args) { 8. ApplicationContext context = new ClassPathXmlApplicationContext("beans-config.xml"); 9. MessageSender sender = (MessageSender)context.getBean("messageSender"); 10. sender.send("message"); 11. } 12. } 执行结果: Log before public abstract void com.savage.simplespring.bean.MessageSender.send(java.lang.String) by LogBeforeAdvice. Send Message[message] by http. 正如你所看到的,在执行MessageSender的send方法前先执行了LogBeforeAdvice的方法!在这个例子中,记录日志的代码并没有横切到我们的业务代码中,LogBeforeAdvice和HttpMessageSender彼此不知道对方的存在,而且我们的应用程序AdviceDemo对LogBeforeAdvice的存在也是一无所知。假如有一天我们的应用程序不需要再业务代码执行前记录日志了,只需要修改XML文件中的定义,而不用更改AdviceDemo的代码: xml 代码 1. bean> 2、After Advice After Advice会在目标对象的方法执行完后执行,你可以通过实现org.springframework.aop.AfterReturingAdvice接口来实现After Advice的逻辑,AfterReturingAdvice接口定义如下: java 代码 1. package org.springframework.aop; 2. 3. public interface AfterReturningAdvice { 4. void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable; 5. } 在afterReturning方法中,你可以获得目标方法执行后的返回值、目标方法对象、目标方法的参数以及目标对象。 继续以上面的例子为例,如果要在MessageSender的send方法执行完后,要再记录日志,那么我们可以先实现AfterReturningAdvice接口: java 代码 1. package com.savage.aop; 2. 3. import org.springframework.aop; 4. 5. public LogAfterAdvice implements AfterReturningAdvice { 6. public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { 7. System.out.println("Log after " + method + " by LogAfterAdvice."); 8. } 9. } 然后在XML文件中指定LogAfterAdvice的实例: xml 代码 1. 2. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. logAfterAdvice 17.
18. 19. 20. 在前面Before Advice的基础上,我们为MessageSender再指定了一个LogAfterAdvice的服务。运行前面的AdviceDemo,结果如下: Send Message[message] by http. Log after public abstract void com.savage.simplespring.bean.MessageSender.send(java.lang.String) by LogAfterAdvice. 3、Around Advice 在上面的LogAfterAdvice例子中,我们通过指定BeforeAdvice和AfterReturingAdvice,在MessageSender的send方法前后执行额外的业务。实际上,如果需要在业务代码执行前后增加额外的服务,你可以直接通过实现org.aopalliance.intercept.MethodInterceptor接口来达到这一目的,MethodInterceptor定义如下: java 代码 1. package org.aopalliance.intercept; 2. 3. public interface MethodInterceptor { 4. public Object invoke(MethodInvocation methodInvocation) throws Throwable; 5. } 例如: java 代码 1. package com.savage.aop; 2. 3. import org.aopalliance.intercept.MethodInterceptor; 4. import org.aopalliance.intercept.MethodInvocation; 5. 6. public class LogAdvice implements MethodInterceptor { 7. public Object invoke(MethodInvocation methodInvocation) throws Throwable { 8. System.out.println("Log before " + methodInvocation.getMethod() + " by LogAdvice."); 9. Object retValue = methodInvocation.proceed(); 10. System.out.println("Log after " + methodInvocation.getMethod() + " by LogAdvice."); 11. return retValue; 12. } 13. } 正如上面所示,在MethodInterceptor中你得自行决定是否调用MethodInvocation的proceed()方法来执行目标对象上的方法,proceed()方法在执行完后会返回目标对象上方法的执行结果。 MethodInterceptor在XML文件中的定义如下: xml 代码 1. 2. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. logAdvice 17.
18. 19. 20. Spring在真正执行目标对象的方法前,会执行interceptorNames中执行的Advice,每个Advice在执行完自己的业务后,会调用MethodInvocation的proceed()方法,将执行的主动权移交给下一个Advice,直到没有下一个Advice为止,在执行完目标对象的方法后,Spring会再以相反的顺序一层层的返回。例如: xml 代码 1. 2. 3. 4. 5. 6. logBeforeAdvice 7. logAdvice 8. logAfterAdvice 9.
10. 11. 象上面这个例子,logBeforeAdvice先会被执行,然后执行logAdvice,接着执行logAfterAdvice,最后又返回到了logAdvice。 现在我们把LogAdvice作一下简单的修改,增加一个id属性,用以在后面查看Advice的调用顺序: java 代码 1. package com.savage.aop; 2. 3. import org.aopalliance.intercept.MethodInterceptor; 4. import org.aopalliance.intercept.MethodInvocation; 5. 6. public class LogAdvice implements MethodInterceptor { 7. private static int INSTANCE_NUM = 0; 8. 9. private int id; 10. 11. public LogAdvice() { 12. id = ++INSTANCE_NUM; 13. } 14. 15. public Object invoke(MethodInvocation methodInvocation) throws Throwable { 16. System.out.println("Log before " + methodInvocation.getMethod() + " by LogAdvice[" + id + "]."); 17. Object retValue = methodInvocation.proceed(); 18. System.out.println("Log after " + methodInvocation.getMethod() + " by LogAdvice[" + id + "]."); 19. return retValue; 20. } 21. } 同时把XML中的定义改为: xml 代码 1. 2. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. logBeforeAdvice 20. logAdvice1 21. logAfterAdvice 22. logAdvice2 23.
24. 25. 26. ...展开收缩
(系统自动生成,下载前可以参看下载内容)
下载文件列表
相关说明
- 本站资源为会员上传分享交流与学习,如有侵犯您的权益,请联系我们删除.
- 本站是交换下载平台,提供交流渠道,下载内容来自于网络,除下载问题外,其它问题请自行百度。
- 本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用WinRAR最新版进行解压.
- 如果您发现内容无法下载,请稍后再次尝试;或者到消费记录里找到下载记录反馈给我们.
- 下载后发现下载的内容跟说明不相乎,请到消费记录里找到下载记录反馈给我们,经确认后退回积分.
- 如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.