JDK创建代理实现AOP

来源:互联网 发布:程序员画流程图工具 编辑:程序博客网 时间:2024/06/06 07:34

 

    拿出抓斗→从船上下抓斗→抓头穿过海底,沉入海底→抓斗达到海底抓取沉积物→抓斗穿出海面→取下抓斗,把抓斗收好。

一、如果对于结构化编程:拿抓斗()→丢抓斗()→抓物品()→拉抓斗()→回收抓斗()

 

二、对于面向对象:船员.拿抓斗→船员.丢抓斗()→抓斗.抓物品()→船员.拉抓斗()→船员.回收抓斗()

三、对于面向切面编程

  有船员这个切面
  船员:船员.拿抓斗→船员.丢抓斗()→船员.拉抓斗()→船员.回收抓斗()
  抓斗:抓斗.抓物品() 

      从比较中,我们可以发现,结构化编程是效率最高的,面向对象最大的优势是方便维护,面向切面不仅仅方便维护,虽然整体流程复杂了,但是对于程序来说,仅仅只要完成抓斗的代码,其他的代码交给Spring这些AOP框架去处理。而且AOP解耦的程度比OOP要高很多。
  
  例如,我们写一个数据操作的时候,一般的流程就是先打开数据库,然后执行操作,最后释放资源和关闭连接,对于不同的业务,主要是执行的操作的变化,而打开数据库和释放资源一般都是类型的。而这种代码在业务中,会分散程序员的注意力。如果我们程序只需要执行里面的操作,不需要把精力放在资源释放和关闭连接上,那对程序员来说就是一种解脱。

 


  1. //定义接口  
  2. package com.greysh.aop.service;  
  3.   
  4. public interface HelloWorld {  
  5.   
  6. public void say();  
  7. }  
  8.   
  9. //对应的实现为  
  10. package com.greysh.aop.service.impl;  
  11.   
  12. import com.greysh.aop.service.HelloWorld;  
  13.   
  14. public class HelloWorldImpl implements HelloWorld {  
  15.   
  16. public void say() {  
  17.   
  18. System.out.println("Say HelloWorld");  
  19. }  
  20. }  
  21. //程序调用的时候  
  22. package com.greysh.aop.test;  
  23.   
  24. import com.greysh.aop.factory.ProxyFactory;  
  25. import com.greysh.aop.service.HelloWorld;  
  26. import com.greysh.aop.service.impl.HelloWorldImpl;  
  27.   
  28. public class TestHelloWorld {  
  29.   
  30. public static void main(String[] args) {  
  31.   
  32. HelloWorld mb = new HelloWorldImpl();  
  33. HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);  
  34. bi.say();  
  35. }  
  36. }  
  37.   
  38. //工厂  
  39. package com.greysh.aop.factory;  
  40.   
  41. import java.lang.reflect.Proxy;  
  42. import com.greysh.aop.proxy.ProxyHandler;  
  43.   
  44. public class ProxyFactory {  
  45.   
  46. public static Object getProxy(Object obj) {  
  47.   
  48. ProxyHandler bn = new ProxyHandler();  
  49. bn.setTarget(obj);  
  50. return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), bn);  
  51. }  
  52. }  
  53.   
  54. //代理和反射类  
  55. package com.greysh.aop.proxy;  
  56.   
  57. import java.lang.reflect.InvocationHandler;  
  58. import java.lang.reflect.Method;  
  59.   
  60. public class ProxyHandler implements InvocationHandler {  
  61.   
  62. private Object target;  
  63. public void setTarget(Object target) {  
  64.   
  65. this.target = target;  
  66. }  
  67.   
  68. @Override  
  69. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  70.   
  71. System.out.println("Before Helloworld");  
  72.   
  73. @SuppressWarnings("unused")  
  74. Object result = method.invoke(target, args);  
  75. System.out.println("Finish Helloworld");  
  76. return null;  
  77. }  
  78. }  
  79.   
  80. //程序运行时候的结果是  
  81.   
  82. Before Helloworld  
  83.   
  84. Say HelloWorld  
  85.   
  86. Finish Helloworld  
  87.   
  88. 如果不是用AOP,那么打印的结果  
  89.   
  90. Say HelloWorld  
  91.   
  92.     
  93.   这5个文件构成一个最简单的AOP的DEMO  
  94.   类似Struts2的拦截器  
  95.   如果两个类实现同一个接口,但是用的时候用一个类代替另一个类,这就是代理模式  
  96.   上述就用了代理模式  
  97.      
  98.   
  99. 当我们调用bi.say(),其实并不是直接用HelloWorldImpl的say(),  
  100.   
  101. 而是  
  102.   
  103. HelloWorld bi = (HelloWorld) ProxyFactory.getProxy(mb);  
  104. 这样ProxyFactory先用ProxyHandler将对象赋值,这里需要调用reflect包,重写里面的invoke方向,这里的invoke在调用的时候先执行  
  105.     
  106. System.out.println("Before Helloworld");  
  107.   
  108.   
  109. 然后用反射  
  110. Object result = method.invoke(target, args);    

 

和我们一般写程序不同,
  不是  对象.方法()
  而是  方法.(对象)
  然后用代理类生产一个实例
  方法为:
  Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), bn);
  当然,第一个参数为类加载器,第二个参数为方法加载器,要加载前面那个类的所有接口。