手动写源码---模拟实现动态代理

AOP的实现有两种,一种是接口的实现,一种是产生自己实现,分别的代表为JDK的Proxy和CGLIB的Proxy

下面是模拟接口代理实现 ,通过模拟JDK的动态代理,更深刻的理解

通过动态代理可以面向切面编程

1 定义被代理的对象和接口

Java代码  收藏代码
  1. public interface BookInterface {  
  2.     void selling();  
  3. }  
Java代码  收藏代码
  1. public interface PhoneInterface {  
  2.     void selling();  
  3. }  
Java代码  收藏代码
  1. public class Book implements BookInterface {  
  2.     @Override  
  3.     public void selling() {  
  4.         System.out.println("books selling.....");  
  5.     }  
  6. }  
Java代码  收藏代码
  1. public class VivoPhone implements PhoneInterface {  
  2.     @Override  
  3.     public void selling() {  
  4.         System.out.println("selling vivo x5");  
  5.     }  
  6. }  

 2 定义切面类

Java代码  收藏代码
  1. public class TimeAspect {  
  2.     static long bgn;  
  3.     public static void before(){  
  4.         bgn = System.currentTimeMillis();  
  5.         System.out.println("begin time...  " + bgn);  
  6.     }  
  7.     public static void after(){  
  8.         long end = System.currentTimeMillis();  
  9.         System.out.println("end time...  " + (end-bgn));  
  10.     }  
  11. }  
Java代码  收藏代码
  1. public class LogAspect{  
  2.     public static void before(){  
  3.            
  4.         System.out.println("begin log...");  
  5.     }  
  6.     public static void after(){  
  7.         System.out.println("finish log...");  
  8.     }  
  9. }  

 3 定义InvocationHander  代理接口

Java代码  收藏代码
  1. import java.lang.reflect.Method;  
  2. public interface InvocationHander {  
  3.     public void invoke(Object o,Method m);  
  4. }  

   代理类(切面编程里面也可以做一些特殊的处理)

Java代码  收藏代码
  1. import java.lang.reflect.Method;  
  2. import jdkproxy.LogTranService;  
  3. import jdkproxy.TimeTranService;  
  4.   
  5. public class ProxyHander implements InvocationHander {  
  6.     private Object target;  
  7.     public ProxyHander(Object target) {  
  8.         this.target = target;  
  9.     }  
  10.     @Override  
  11.     public void invoke(Object o, Method m) {  
  12.         try {  
  13.             TimeTranService.before();  
  14.             if(!(o instanceof BookInterface)){//只有非BookInterface接口调用日志  
  15.                 LogTranService.before();  
  16.             }  
  17.               
  18.             m.invoke(target);  
  19.                
  20.             if(!(o instanceof BookInterface)){  
  21.                 LogTranService.after();  
  22.             }  
  23.             TimeTranService.after();  
  24.         } catch (Exception e) {  
  25.             e.printStackTrace();  
  26.         }   
  27.     }  
  28. }  

    动态代理类

Java代码  收藏代码
  1. import java.io.File;  
  2. import java.io.IOException;  
  3. import java.lang.reflect.Constructor;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import javax.tools.JavaCompiler;  
  7. import javax.tools.JavaCompiler.CompilationTask;  
  8. import javax.tools.StandardJavaFileManager;  
  9. import javax.tools.ToolProvider;  
  10.   
  11.   
  12. import org.apache.commons.io.FileUtils;  
  13.   
  14. public class Proxy {  
  15.     /* 
  16.      * 空的构造函数 
  17.      */  
  18.     private Proxy(){  
  19.     }  
  20.     /* 
  21.      * 返回代理类 
  22.      */  
  23.     public static Object newProxyInstance(Class inter,InvocationHander h){  
  24.         String packageName  = inter.getPackage().getName();  
  25.         // String temp = new String(packageName);  
  26.         String proxyClassName = "$"+packageName.replace(".","_") + "_" + inter.getSimpleName() +"Proxy";  
  27.           
  28.         String InHanderPackage = h.getClass().getPackage().getName();  
  29.         String rt = " ";// 换行  
  30.         String methodCode = "";  
  31.         for (Method method:inter.getMethods()) {  
  32.             methodCode+="   @Override"+rt+  
  33.               
  34.             "   public void "+ method.getName()+"() {"+rt+  
  35.             "       try{"+rt+  
  36.             "           Method method  = "+inter.getName()+".class.getMethod(""   
  37.             +           method.getName()+   "");"+rt+  
  38.             "           h.invoke(this,method);      "+rt+  
  39.             "       }catch(Exception e ){" +rt+  
  40.             "           e.printStackTrace();" +rt+  
  41.             "       }"+rt+  
  42.             "   }";  
  43.         }  
  44.         /* 
  45.          * 总的java代码 
  46.          */  
  47.         String javaCode=    
  48.         "package  "+packageName+";"+rt+  
  49.         "import "+InHanderPackage+".InvocationHander;"+rt+  
  50.           
  51.         "import java.lang.reflect.Method;"+rt+  
  52.         "public class "+proxyClassName+" implements "+inter.getName()+" {"+rt+  
  53.         "   public "+proxyClassName+"("+InHanderPackage+".InvocationHander h) {"+rt+  
  54.         "       super();"+rt+  
  55.         "       this.h = h;"+rt+  
  56.         "   }"+rt+  
  57.         "   private "+InHanderPackage+".InvocationHander h;"+rt+  
  58.         methodCode+rt+  
  59.         "}";  
  60.         /* 
  61.          *  生成java文件 
  62.          */  
  63.         // 生成文件路径  
  64.         String filename =  System.getProperty("user.dir")+"/bin/"+packageName.replace(".", "//")+"/"+proxyClassName+".java";  
  65.         File file = new File(filename);  
  66.         try {  
  67.             // 需要commons-io的jar方便的操作文件  
  68.             FileUtils.writeStringToFile(file, javaCode);   
  69.         } catch (IOException e) {  
  70.             e.printStackTrace();  
  71.         }  
  72.           
  73.           
  74.         // 编译  拿到编译器  
  75.         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();  
  76.         // 文件管理  
  77.         StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);  
  78.         //获取文件  
  79.         Iterable units = fileMgr.getJavaFileObjects(filename);  
  80.           
  81.         // 编译任务  
  82.         CompilationTask t  = compiler.getTask(null, fileMgr, null, null, null, units);  
  83.         // call进行编译  
  84.         t.call();  
  85.         try {  
  86.             fileMgr.close();  
  87.         } catch (IOException e) {  
  88.             e.printStackTrace();  
  89.         }  
  90.           
  91.         // load到内存  
  92.         ClassLoader cl = ClassLoader.getSystemClassLoader();  
  93.         try {  
  94.             Class c = cl.loadClass(packageName+"."+proxyClassName);  
  95.             Constructor ctr = c.getConstructor(InvocationHander.class);  
  96.             return ctr.newInstance(h);  
  97.         } catch (Exception e) {  
  98.             e.printStackTrace();  
  99.         }  
  100.         return null;  
  101.     }  
  102. }  

4 测试

Java代码  收藏代码
  1. import org.junit.After;  
  2. import org.junit.Before;  
  3. import org.junit.Test;  
  4. public class TestProxy {  
  5.     @Before  
  6.     public void  before(){  
  7.         System.out.println("-----------------start-------------------");  
  8.     }  
  9.     @Test  
  10.     public  void test() {  
  11.         Book book = new Book();  
  12.         InvocationHander h = new ProxyHander(book);  
  13.         BookInterface bi = (BookInterface)Proxy.newProxyInstance(BookInterface.class,h);  
  14.         bi.selling(); // 没有日志打印  
  15.           
  16.         System.out.println("==================分割==============================");  
  17.           
  18.         PhoneInterface car = new VivoPhone();  
  19.         h = new ProxyHander(car);  
  20.         PhoneInterface pi = (PhoneInterface)Proxy.newProxyInstance(PhoneInterface.class,h);  
  21.         pi.selling(); // 有日志打印  
  22.     }  
  23.     @After  
  24.     public void  after(){  
  25.         System.out.println("-----------------end-------------------");    
  26.     }  
  27. }  

 Proxy类里面生成代理类名称的方法是根据包名来的,全类名长度加起来超过250多个长度可能会让java类无法编译,那就需要特殊处理了。超过250个长度的全类名那种项目没见过,不考虑

上面是他的原理,spring中如何使用aop呢?

 请参考

 参考文章  

原文地址:https://www.cnblogs.com/xm1-ybtk/p/5112118.html