1、Spring提供俩种方式实现AOPAOP是Aspect Oriented Programming的缩写,意思是面向方面编程,一种新兴的编程技术。 AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦, AOP可以说也是这种目标的一种实现。它可以解决OOP和过程化方法不能够很好解决的横切 (crosscut)问题, 如:事务、安全、日志等横切关注。当未来系统变得越来越复杂, 横切关注点就成为一个大问题的时候,AOP就可以很轻松的解决横切关注点这个问题。 比如有这样一个情景: Java代码 1. publicclassAccountManager2. private
2、staticfinalsysLogger=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(accesssucce
3、ssfully);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 fin
4、al 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 s
5、uccessfully); 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!); 这个例子虽然是很好的面向对象代码,但是在业务处理逻辑中夹杂这日志处理和权限判断,变得复杂混乱. 在 AO
6、P 中,正交关注点(如安全和日志记录)被识别为系统中的常见横切关注点。说它们是横切, 是因为它们总是切入模块(如包、类和代码文件)的多个单位。也许横切关注点可能不是核心业务逻辑的一部分,但是它们是应用程序的基本部分。 AOP的实现主要是通过方法的拦截实现.在不使用AOP框架的情况下,我们可以通过JDK提供的动态代理来实现方法的拦截 注意:使用JDK提供的动态代理实现 要求我们的目标对象必须实现接口 IUserBean接口 Java代码 1. packagecom.royzhou.aop;2. 3. publicinterfaceIUserBean4. 5. publicvoidgetUser(
7、);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;
8、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.
9、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 I
10、UserBean 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!); pub
11、lic 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 st
12、atic Object newProxyInstance(ClassLoader loader, Class interfaces, InvocationHandler h) 方法可以生成一个动态代理对象 其中 loader是类装载器 interfaces是目标对象实现的一系列接口 h是一个实现InvocationHandler接口的类,我们对代理对象的所有操作都经过它处理 这样我们就可以拦截到UserBean的方法,在方法执行前先判断是否有权限,如果有则执行方法, 没有权限的话就不执行方法. 编写我们的代理类: JDKProxy.java Java代码 1. packagecom.royzh
13、ou.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、. /生成代理对象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.getUser
15、Name();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;publi
16、c 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); pu
17、blic 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
18、; 通过调用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.ao
19、p;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. publicclassTestProxy
20、4. 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 us
21、erBean = (IUserBean) jProxy.createProxyObject(new UserBean(); userBean.addUser(); 即当用户没有权限时,控制台不输出东西,说明我们拦截方法对其做的权限判断生效了. 从上面这个例子可以成功拦截了调用的方法并对其做了相应的处理 如果不使用JDK提供的Proxy类 通过cglib创建代理类,好处是不要求我们的目标对象实现接口 Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(this.targetObject.getClass(); enhancer.s
22、etCallback(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=
23、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.pr
24、intln(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
25、) 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. importnet.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1