Spring提供俩种方式实现AOP.doc_第1页
Spring提供俩种方式实现AOP.doc_第2页
Spring提供俩种方式实现AOP.doc_第3页
Spring提供俩种方式实现AOP.doc_第4页
Spring提供俩种方式实现AOP.doc_第5页
已阅读5页,还剩17页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

AOP是Aspect Oriented Programming的缩写,意思是面向方面编程,一种新兴的编程技术。 AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦, AOP可以说也是这种目标的一种实现。它可以解决OOP和过程化方法不能够很好解决的横切 (crosscut)问题, 如:事务、安全、日志等横切关注。当未来系统变得越来越复杂, 横切关注点就成为一个大问题的时候,AOP就可以很轻松的解决横切关注点这个问题。 比如有这样一个情景: Java代码 1. publicclassAccountManager2. privatestaticfinalsysLogger=SystemLogger.getInstance();3. privateAuthorizationManagerauthMgr=newAuthorizationManager();4. 5. publicvoidtransferFunds(Stringfrom,Stringto,intamount)6. sysLogger.log(transferfundsfrom+from+to+to);7. if(authMgr.accessAble(from)&authMgr.accessAble(to)8. sysLogger.log(accesssuccessfully);9. CustomerAccountfrom=findAccount(from);10. CustomerAccountto=findAccount(to);11. from.debit(amount);12. to.credit(amount);13. else14. sysLogger.log(accessdeny);15. 16. sysLogger.log(transferfundsfrom+from+to+to+$+amount+successfully!);17. 18. public class AccountManager private static final sysLogger = SystemLogger.getInstance();private AuthorizationManager authMgr = new AuthorizationManager();public void transferFunds(String from, String to, int amount) sysLogger.log(transfer funds from + from + to + to);if(authMgr.accessAble(from) & authMgr.accessAble(to) sysLogger.log(access successfully);CustomerAccount from = findAccount(from); CustomerAccount to = findAccount(to);from.debit(amount);to.credit(amount); else sysLogger.log(access deny);sysLogger.log(transfer funds from + from + to + to + $ + amount + successfully!);这个例子虽然是很好的面向对象代码,但是在业务处理逻辑中夹杂这日志处理和权限判断,变得复杂混乱. 在 AOP 中,正交关注点(如安全和日志记录)被识别为系统中的常见横切关注点。说它们是横切, 是因为它们总是切入模块(如包、类和代码文件)的多个单位。也许横切关注点可能不是核心业务逻辑的一部分,但是它们是应用程序的基本部分。 AOP的实现主要是通过方法的拦截实现.在不使用AOP框架的情况下,我们可以通过JDK提供的动态代理来实现方法的拦截 注意:使用JDK提供的动态代理实现 要求我们的目标对象必须实现接口 IUserBean接口 Java代码 1. packagecom.royzhou.aop;2. 3. publicinterfaceIUserBean4. 5. publicvoidgetUser();6. 7. publicvoidaddUser();8. 9. publicvoidupdateUser();10. 11. publicvoiddeleteUser();12. package com.royzhou.aop;public interface IUserBean public void getUser();public void addUser();public void updateUser();public void deleteUser();IUserBean实现类 UserBean.java Java代码 1. packagecom.royzhou.aop;2. 3. publicclassUserBeanimplementsIUserBean4. 5. privateStringuser=null;6. 7. publicUserBean()8. 9. 10. publicUserBean(Stringuser)11. this.user=user;12. 13. 14. publicvoidsetUser(Stringuser)15. this.user=user;16. 17. 18. publicvoidaddUser()19. System.out.println(thisisaddUser()method!);20. 21. 22. publicvoiddeleteUser()23. System.out.println(thisisdeleteUser()method!);24. 25. 26. publicvoidgetUser()27. System.out.println(thisisgetUser()method!);28. 29. 30. publicvoidupdateUser()31. System.out.println(thisisupdateUser()method!);32. 33. package com.royzhou.aop;public class UserBean implements IUserBean private String user = null;public UserBean() public UserBean(String user) this.user = user;public void setUser(String user) this.user = user;public void addUser() System.out.println(this is addUser() method!);public void deleteUser() System.out.println(this is deleteUser() method!);public void getUser() System.out.println(this is getUser() method!);public void updateUser() System.out.println(this is updateUser() method!);我们希望在UserBean执行方法之前先检查userName是不是为空,以此做为权限判断. 当然我们可以在没个方法里面去加这些判断,但是这需要为每个方法都添加同样的判断,维护不便. 使用JDK提供的动态代理技术可以很方便的实现上面的需求: 通过java.lang.reflect.Proxy;提供的 public static Object newProxyInstance(ClassLoader loader, Class interfaces, InvocationHandler h) 方法可以生成一个动态代理对象 其中 loader是类装载器 interfaces是目标对象实现的一系列接口 h是一个实现InvocationHandler接口的类,我们对代理对象的所有操作都经过它处理 这样我们就可以拦截到UserBean的方法,在方法执行前先判断是否有权限,如果有则执行方法, 没有权限的话就不执行方法. 编写我们的代理类: JDKProxy.java Java代码 1. packagecom.royzhou.aop;2. 3. importjava.lang.reflect.InvocationHandler;4. importjava.lang.reflect.Method;5. importjava.lang.reflect.Proxy;6. 7. publicclassJDKProxyimplementsInvocationHandler8. 9. privateObjecttargetObject;10. 11. publicObjectcreateProxyObject(ObjecttargetObject)12. this.targetObject=targetObject;13. /生成代理对象14. returnProxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this);15. 16. 17. publicObjectinvoke(Objectproxy,Methodmethod,Objectargs)throwsThrowable18. UserBeanuserBean=(UserBean)targetObject;19. StringuserName=userBean.getUserName();20. Objectresult=null;21. /权限判断22. if(userName!=null&!.equals(userName)23. /调用目标对象的方法24. result=method.invoke(targetObject,args);25. 26. returnresult;27. 28. package com.royzhou.aop;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class JDKProxy implements InvocationHandler private Object targetObject;public Object createProxyObject(Object targetObject) this.targetObject = targetObject;/生成代理对象return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(),this.targetObject.getClass().getInterfaces(),this);public Object invoke(Object proxy, Method method, Object args) throws Throwable UserBean userBean = (UserBean) targetObject;String userName = userBean.getUserName();Object result = null;/权限判断if(userName!=null & !.equals(userName) /调用目标对象的方法result = method.invoke(targetObject, args); return result;通过调用createProxyObject可以生成代理对象, 编写测试类如下: Java代码 1. packagecom.royzhou.aop;2. 3. publicclassTestProxy4. 5. publicstaticvoidmain(Stringargs)6. JDKProxyjProxy=newJDKProxy();7. IUserBeanuserBean=(IUserBean)jProxy.createProxyObject(newUserBean(royzhou);8. userBean.addUser();9. 10. package com.royzhou.aop;public class TestProxy public static void main(String args) JDKProxy jProxy = new JDKProxy();IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean(royzhou);userBean.addUser();执行成功后输出: this is addUser() method! 再次修改测试类: Java代码 1. packagecom.royzhou.aop;2. 3. publicclassTestProxy4. 5. publicstaticvoidmain(Stringargs)6. JDKProxyjProxy=newJDKProxy();7. IUserBeanuserBean=(IUserBean)jProxy.createProxyObject(newUserBean();8. userBean.addUser();9. 10. package com.royzhou.aop;public class TestProxy public static void main(String args) JDKProxy jProxy = new JDKProxy();IUserBean userBean = (IUserBean) jProxy.createProxyObject(new UserBean();userBean.addUser();即当用户没有权限时,控制台不输出东西,说明我们拦截方法对其做的权限判断生效了. 从上面这个例子可以成功拦截了调用的方法并对其做了相应的处理 如果不使用JDK提供的Proxy类 通过cglib创建代理类,好处是不要求我们的目标对象实现接口 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass(); enhancer.setCallback(this); /回调,参数是一个实现MethodInterceptor接口的类,我们对代理对象的所有操作都经过它处理 return enhancer.create(); /创建代理对象 修改UserBean 去掉IUserBean接口 Java代码 1. packagecom.royzhou.aop;2. 3. publicclassUserBean4. 5. privateStringuserName=null;6. 7. publicUserBean()8. 9. 10. publicUserBean(StringuserName)11. this.userName=userName;12. 13. 14. publicvoidaddUser()15. System.out.println(thisisaddUser()method!);16. 17. 18. publicvoiddeleteUser()19. System.out.println(thisisdeleteUser()method!);20. 21. 22. publicvoidgetUser()23. System.out.println(thisisgetUser()method!);24. 25. 26. publicvoidupdateUser()27. System.out.println(thisisupdateUser()method!);28. 29. 30. publicStringgetUserName()31. returnuserName;32. 33. 34. publicvoidsetUserName(StringuserName)35. this.userName=userName;36. 37. package com.royzhou.aop;public class UserBean private String userName = null;public UserBean() public UserBean(String userName) this.userName = userName;public void addUser() System.out.println(this is addUser() method!);public void deleteUser() System.out.println(this is deleteUser() method!);public void getUser() System.out.println(this is getUser() method!);public void updateUser() System.out.println(this is updateUser() method!);public String getUserName() return userName;public void setUserName(String userName) this.userName = userName;通过cglib创建代理类 CGLibProxy.java Java代码 1. packagecom.royzhou.aop;2. 3. importjava.lang.reflect.Method;4. 5. xy.Enhancer;6. xy.MethodInterceptor;7. xy.MethodProxy;8. 9. publicclassCGLibProxyimplementsMethodInterceptor10. 11. privateObjecttargetObject;12. 13. publicObjectcreateProxyObject(ObjecttargetObject)14. this.targetObject=targetObject;15. Enhancerenhancer=newEnhancer();16. enhancer.setSuperclass(this.targetObject.getClass();/非final进行覆盖17. enhancer.setCallback(this);/回调,通过18. returnenhancer.create();/创建代理对象19. 20. 21. publicObjectintercept(Objectproxy,Methodmethod,Objectargs,MethodProxymethodProxy)throwsThrowable22. UserBeanuserBean=(UserBean)targetObject;23. StringuserName=userBean.getUserName();24. Objectresult=null;25. if(userName!=null&!.equals(userName)26. /调用目标对象的方法27. result=methodProxy.invoke(targetObject,args);28. 29. returnresult;30. 31. package com.royzhou.aop;import java.lang.reflect.Method;import xy.Enhancer;import xy.MethodInterceptor;import xy.MethodProxy;public class CGLibProxy implements MethodInterceptor private Object targetObject;public Object createProxyObject(Object targetObject) this.targetObject = targetObject;Enhancer enhancer = new Enhancer();enhancer.setSuperclass(this.targetObject.getClass(); /非final 进行覆盖enhancer.setCallback(this); /回调,通过return enhancer.create(); /创建代理对象public Object intercept(Object proxy, Method method, Object args, MethodProxy methodProxy) throws Throwable UserBean userBean = (UserBean) targetObject;String userName = userBean.getUserName();Object result = null;if(userName!=null & !.equals(userName) /调用目标对象的方法result = methodProxy.invoke(targetObject, args); return result;编写测试类: Java代码 1. packagecom.royzhou.aop;2. 3. publicclassTestProxy4. 5. publicstaticvoidmain(Stringargs)6. CGLibProxycProxy=newCGLibProxy();7. UserBeanuserBean=(UserBean)cProxy.createProxyObject(newUserBean(royzhou);8. userBean.addUser();9. 10. package com.royzhou.aop;public class TestProxy public static void main(String args) CGLibProxy cProxy = new CGLibProxy();UserBean userBean = (UserBean) cProxy.createProxyObject(new UserBean(royzhou);userBean.addUser();输出: this is addUser() method! 当取消用户权限时,控制台不输出任何东西. 说明通过CGLib成功生成代理对象,拦截了目标对象的方法. Spring主要通过代理来实现AOP 下面是AOP的一些基本概念: 切面(Aspect):对横切关注点的抽象(类似类对对象的抽象) 连接点(JoinPoint):被拦截到的点,泛指方法 切入点(CutPoint):对哪些连接点进行拦截的定义 通知(Advice):在特定的连接点,AOP框架执行的动作.前置/后置/例外/最终/环绕通知(调用方法之前执行,全部执行完毕之后) 引入(Introduction): 添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。 目标对象(Target Object): 包含连接点的对象。也被称作 被通知或被代理对象。 AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时 完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样, 在运行时完成织入。 Adive通知可理解如下: Java代码 1. publicObjectinvoke(Objectproxy,Methodmethod,Objectargs)throwsThrowable2. UserBeanuserBean=(UserBean)targetObject;3. StringuserName=userBean.getUserName();4. Objectresult=null;5. if(userName!=null&!.equals(userName)6. /调用目标对象的方法7. try8. /前置通知9. result=method.invoke(targetObject,args);10. /后置通知11. catch(Exceptione)12. /例外通知13. finally14. /最终通知15. 16. 17. /环绕通知(前置通知之后,目标对象方法调用之前执行,全部执行完毕(最终通知)之后)18. returnresult;19. public Object invoke(Object proxy, Method method, Object args) throws Throwable UserBean userBean = (UserBean) targetObject;String userName = userBean.getUserName();Object result = null;if(userName!=null & !.equals(userName) /调用目标对象的方法try /前置通知result = method.invoke(targetObject, args);/后置通知 catch(Exception e) /例外通知 finally /最终通知 /环绕通知(前置通知之后,目标对象方法调用之前执行,全部执行完毕(最终通知)之后)return result;Spring提供两种方式实现AOP 一种是XML配置的方式 一种是annotation注解的方式 不管采用哪种方式,都必须在spring的配置文件中配置AOP支持: Xml代码 1. 2. 10. 11. 其中表示打开aspect注解处理器 (aspect的内容具体可查看/developerworks/cn/java/j-aspectj/) 使用注解方式实现AOP必须引入三个jar包: aspectjweaver.jar aspectjrt.jar cglib.jar 首先建立好测试用的业务bean 然后我们需要定义一个切面/定义切入点/通知等 接口IUserBean.java Java代码 1. packagecom.royzhou.aop;2. 3. publicinterfaceIUserBean4. 5. publicvoidgetUser();6. 7. publicvoidaddUser();8. 9. publicvoidupdateUser();10. 11. publicvoiddeleteUser();12. package com.royzhou.aop;public interface IUserBean public void getUser();public void addUser();public void updateUser();public void deleteUser();实现类UserBean.java Java代码 1. packagecom.royzhou.aop;2. 3. publicclassUserBean4. 5. publicvoidaddUser(StringuserName)6. System.out.println(thisisaddUser()method!);7. 8. 9. publicvoiddeleteUser(intuserId)10. System.out.println(thisisdeleteUser()method!);11. 12. 13. publicStringgetUser(StringuserId)14. System.out.println(thisisgetUser()method!);15. returnhaha;16. 17. 18. publicvoidupdateUser(intuserId,StringuserName)19. System.out.println(thisisupdateUser()method!);20. 21. package com.royzhou.aop;public class UserBean public void addUser(String userName) System.out.println(this is addUser() method!);public void deleteUser(int userId) System.out.println(this is deleteUser() method!);public String getUser(String userId) System.out.println(this is getUser() method!);return haha;public void updateUser(int userId, String userName) System.o

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论