`

jdk动态代理实现原理

    博客分类:
  • Java
 
阅读更多

写在前面:

大神和diao炸天的亲请绕道..

关于代理模式的概念这里省去,大家可以放鸟尽情搜..

关于为什么叫动态代理,个人理解是代理的类是在运行时动态生成的,大家也可以参考网上的理解..

文笔很差,所以文字较少,都在代码和注释中..

 

=======一点不华丽的分割线-------------------------

开门见山,lets go..

 

java中可以通过jdk提供的 Proxy.newProxyInstance静态方法来创建动态代理对象,下面先来看看这个方法的实现

 

[java] view plaincopy
 
  1. public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)  
  2.            throws IllegalArgumentException {  
  3.        //InvocationHandler不能为空,因为对代理对象的所有方法调用实际上都会委托到InvocationHandler的invoke方法,  
  4.        //这个我们后面通过查看产生的代理类的源代码便会一目了然  
  5.        if (h == null) {  
  6.            throw new NullPointerException();  
  7.        }  
  8.   
  9.        //这个是核心的地方,通过提供的ClassLoader和interface列表来产生代理类,具体的实现可以参考getProxyClass这个方法的实现,  
  10.        //真正的工作是由sun.misc.ProxyGenerator这个类来完成的,可以google查看具体的逻辑.在我们的程序中通过设置  
  11.        //System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true")可以查看产生的类文件  
  12.        Class cl = getProxyClass(loader, interfaces);  
  13.   
  14.        //因为代理类继承了Proxy类.而Proxy中定义了构造函数protected Proxy(InvocationHandler h),所以可以反射得到Constructer实例  
  15.        //创建代理对象  
  16.        try {  
  17.            Constructor cons = cl.getConstructor(constructorParams);  
  18.            return (Object) cons.newInstance(new Object[] { h });  
  19.        } catch (NoSuchMethodException e) {  
  20.            throw new InternalError(e.toString());  
  21.        } catch (IllegalAccessException e) {  
  22.            throw new InternalError(e.toString());  
  23.        } catch (InstantiationException e) {  
  24.            throw new InternalError(e.toString());  
  25.        } catch (InvocationTargetException e) {  
  26.            throw new InternalError(e.toString());  
  27.        }  
  28.    }  


下面通过个例子来说明下:

 

先来定义一个接口,jdk的动态代理基于接口来创建代理类,不能基于类的原因是java不支持多重继承,而代理类都会继承Proxy类(个人理解).

 

[java] view plaincopy
 
  1. /** 
  2.  * Subject 
  3.  *  
  4.  * @author Kevin Fan 
  5.  * @since 2013-9-13 下午2:43:33 
  6.  */  
  7. public interface Subject {  
  8.     void pub(String key, String content);  
  9.   
  10.     String sub(String key);  
  11. }  


再来一个具体的实现,在代理模式中可以叫它的实例可以叫target,这个是真正执行操作的对象

 

 

[java] view plaincopy
 
  1. /** 
  2.  * SimpleSubject 
  3.  *  
  4.  * @author Kevin Fan 
  5.  * @since 2013-9-13 下午2:45:03 
  6.  */  
  7. public class SimpleSubject implements Subject {  
  8.     private Map<String, String> msg = new ConcurrentHashMap<String, String>();  
  9.   
  10.     public void pub(String key, String content) {  
  11.         System.out.println("pub msg: key is " + key + ", content is " + content);  
  12.         msg.put(key, content);  
  13.     }  
  14.   
  15.     public String sub(String key) {  
  16.         if (msg.containsKey(key)) {  
  17.             String ret = msg.get(key);  
  18.             System.out.println("sub msg: key is " + key + ", result is " + ret);  
  19.             return ret;  
  20.         }  
  21.   
  22.         return null;  
  23.     }  
  24.   
  25. }  


好,接下来我们来写个动态代理工厂,根据 不同的target来创建动态代理对象

 

 

[java] view plaincopy
 
  1. /** 
  2.  * SubjectProxyFactory 
  3.  *  
  4.  * @author Kevin Fan 
  5.  * @since 2013-9-13 下午2:47:24 
  6.  */  
  7. public class SubjectProxyFactory {  
  8.     //TODO: cache   
  9.     public static Subject getSubject(final Subject realSubject) {  
  10.         return (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), new Class[] { Subject.class },  
  11.                 new InvocationHandler() {  
  12.   
  13.                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  14.                         System.out.println("\naction before method invocation....");  
  15.                         Object retVal = method.invoke(realSubject, args);  
  16.                         System.out.println("action after method invocation....\n");  
  17.                         return retVal;  
  18.                     }  
  19.                 });  
  20.     }  
  21. }  

 

可以看到这是一个简单的实现,只是在真实对象执行前后各打一句信息..

 

接下来用一个 main函数来把这些结合起来 

 

[java] view plaincopy
 
  1. /** 
  2.  * Demo 
  3.  *  
  4.  * @author Kevin Fan 
  5.  * @since 2013-9-13 下午2:50:28 
  6.  */  
  7. public class Demo {  
  8.     public static void main(String[] args) {  
  9.         //设置此系统属性,以查看代理类文件  
  10.         System.setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles""true");  
  11.           
  12.         //创建真实对象  
  13.         Subject subj = new SimpleSubject();  
  14.         subj.pub("name""kevin.fan");  
  15.         subj.sub("name");  
  16.           
  17.         //创建代理对象  
  18.         Subject proxy = SubjectProxyFactory.getSubject(subj);  
  19.         proxy.pub("hobby""r&b music");  
  20.         proxy.sub("name");  
  21.     }  
  22. }  


ok,小手抖一下,走你,看下执行结果

 

 

[html] view plaincopy
 
  1. pub msg: key is name, content is kevin.fan  
  2. sub msg: key is name, result is kevin.fan  
  3.   
  4.   
  5. action before method invocation....  
  6. pub msg: key is hobby, content is r&b music  
  7. action after method invocation....  
  8.   
  9.   
  10.   
  11.   
  12. action before method invocation....  
  13. sub msg: key is name, result is kevin.fan  
  14. action after method invocation....  


可以看到在调用代理对象的方法时,添加的额外动作已经生效,接下来我们看下生成的代理类的代码..

 

 

 

[java] view plaincopy
 
  1. import com.aliyun.demo.kevin.coder.lang.proxy.Subject;  
  2. import java.lang.reflect.InvocationHandler;  
  3. import java.lang.reflect.Method;  
  4. import java.lang.reflect.Proxy;  
  5. import java.lang.reflect.UndeclaredThrowableException;  
  6.   
  7. //这里很清楚了,代理类继承了Proxy类,并且实现了Proxy.newProxyInstance这个方法中传入的接口  
  8. public final class $Proxy0 extends Proxy  
  9.   implements Subject  
  10. {  
  11.     
  12.   //这些方法在下面的static init block中进行初始化  
  13.   private static Method m4;  
  14.   private static Method m1;  
  15.   private static Method m3;  
  16.   private static Method m0;  
  17.   private static Method m2;  
  18.     
  19.   static  
  20.   {  
  21.     try  
  22.     {  
  23.       m4 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("sub"new Class[] { Class.forName("java.lang.String") });  
  24.       m1 = Class.forName("java.lang.Object").getMethod("equals"new Class[] { Class.forName("java.lang.Object") });  
  25.       m3 = Class.forName("com.aliyun.demo.kevin.coder.lang.proxy.Subject").getMethod("pub"new Class[] { Class.forName("java.lang.String"), Class.forName("java.lang.String") });  
  26.       m0 = Class.forName("java.lang.Object").getMethod("hashCode"new Class[0]);  
  27.       m2 = Class.forName("java.lang.Object").getMethod("toString"new Class[0]);  
  28.       return;  
  29.     }  
  30.     catch (NoSuchMethodException localNoSuchMethodException)  
  31.     {  
  32.       throw new NoSuchMethodError(localNoSuchMethodException.getMessage());  
  33.     }  
  34.     catch (ClassNotFoundException localClassNotFoundException)  
  35.     {  
  36.       throw new NoClassDefFoundError(localClassNotFoundException.getMessage());  
  37.     }  
  38.   }  
  39.   
  40.   //构造函数,接收一个 InvocationHandler作为参数,这就是为什么Proxy.newProxyInstance方法里可以  
  41.   //通过InvocationHandler实例作为参数来反射获取Constructer实例   
  42.   public $Proxy0 paramInvocationHandler)  
  43.     throws   
  44.   {  
  45.     super(paramInvocationHandler);  
  46.   }  
  47.   
  48.   //下面通过这个来看下代理对象中方法是怎样调用的  
  49.   public final String sub(String paramString)  
  50.     throws   
  51.   {  
  52.     try  
  53.     {  
  54.        //全部是通过调用InvocationHandler的invoke方法,传入对应的方法和参数  
  55.       return (String)this.h.invoke(this, m4, new Object[] { paramString });  
  56.     }  
  57.     catch (Error|RuntimeException localError)  
  58.     {  
  59.       throw localError;  
  60.     }  
  61.     catch (Throwable localThrowable)  
  62.     {  
  63.       throw new UndeclaredThrowableException(localThrowable);  
  64.     }  
  65.   }  
  66.   
  67.   public final boolean equals(Object paramObject)  
  68.     throws   
  69.   {  
  70.     try  
  71.     {  
  72.       return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();  
  73.     }  
  74.     catch (Error|RuntimeException localError)  
  75.     {  
  76.       throw localError;  
  77.     }  
  78.     catch (Throwable localThrowable)  
  79.     {  
  80.       throw new UndeclaredThrowableException(localThrowable);  
  81.     }  
  82.   }  
  83.   
  84.   public final void pub(String paramString1, String paramString2)  
  85.     throws   
  86.   {  
  87.     try  
  88.     {  
  89.       this.h.invoke(this, m3, new Object[] { paramString1, paramString2 });  
  90.       return;  
  91.     }  
  92.     catch (Error|RuntimeException localError)  
  93.     {  
  94.       throw localError;  
  95.     }  
  96.     catch (Throwable localThrowable)  
  97.     {  
  98.       throw new UndeclaredThrowableException(localThrowable);  
  99.     }  
  100.   }  
  101.   
  102.   public final int hashCode()  
  103.     throws   
  104.   {  
  105.     try  
  106.     {  
  107.       return ((Integer)this.h.invoke(this, m0, null)).intValue();  
  108.     }  
  109.     catch (Error|RuntimeException localError)  
  110.     {  
  111.       throw localError;  
  112.     }  
  113.     catch (Throwable localThrowable)  
  114.     {  
  115.       throw new UndeclaredThrowableException(localThrowable);  
  116.     }  
  117.   }  
  118.   
  119.   public final String toString()  
  120.     throws   
  121.   {  
  122.     try  
  123.     {  
  124.       return (String)this.h.invoke(this, m2, null);  
  125.     }  
  126.     catch (Error|RuntimeException localError)  
  127.     {  
  128.       throw localError;  
  129.     }  
  130.     catch (Throwable localThrowable)  
  131.     {  
  132.       throw new UndeclaredThrowableException(localThrowable);  
  133.     }  
  134.   }  
  135.   
  136. }  
分享到:
评论

相关推荐

    Java JDK动态代理实现原理实例解析

    Java JDK动态代理实现原理实例解析 Java JDK动态代理实现原理实例解析是指通过Java JDK提供的代理机制来实现动态代理的原理和实例解析。动态代理是一种非常重要的设计模式,它可以在运行时生成代理类,从而实现了...

    JDK动态代理_JDK动态代理

    本文将详细介绍JDK动态代理的原理与应用,帮助读者深入理解其工作方式以及如何在实际项目中运用。 #### 二、JDK动态代理简介 JDK动态代理是Java平台提供的一个工具包,用于在运行时创建代理对象。它主要适用于实现...

    JDK动态代理 spring aop 的原理

    现在让我们深入探讨JDK动态代理和Spring AOP的原理。 首先,JDK动态代理基于Java的反射机制,通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,...

    关于jdk动态代理的源码剖析

    - **只能代理实现了接口的类**:这是JDK动态代理的一个限制,如果目标对象没有实现任何接口,则无法使用JDK动态代理。 - **性能开销**:虽然这种开销通常很小,但在高并发场景下可能会成为瓶颈。 通过上述分析,...

    JDK动态代理源码

    在Java编程领域,JDK动态代理是一个非常重要的概念,它允许我们在...理解并掌握JDK动态代理的原理和用法,能够帮助我们更灵活地设计和实现程序,特别是在需要扩展或增强已有功能时,动态代理提供了一种优雅的解决方案。

    Spring Aop的底层实现技术 --- Jdk动态代理原理

    Spring AOP 的底层实现技术 --- Jdk 动态代理原理 JDK 动态代理是 Spring AOP 的底层实现技术,允许开发者在运行期创建接口的代理实例。在 JDK 1.3 以后,JDK 动态代理技术提供了实现 AOP 的绝好底层技术。JDK 动态...

    JDK动态代理简单示例

    除了基本的代理实现,JDK动态代理还可以结合其他设计模式,如工厂模式,创建更加复杂的代理对象。此外,Spring框架中的AOP功能也是基于JDK动态代理或CGLIB实现的,它允许开发者定义切面,对满足特定条件的方法进行...

    模拟JDK动态代理内部实现

    在本文中,我们将深入探讨如何模拟JDK的动态代理内部实现。 首先,我们需要了解JDK动态代理的基础知识。Java中的动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口实现。`Proxy...

    Jdk动态代理和cglib动态代理原理

    - **JDK代理**适用于目标类实现有接口的情况,更符合面向接口的设计原则,且无需引入额外的库。 - **CGLIB代理**适用于目标类没有接口或者不希望修改原有接口的情况,其性能通常优于JDK代理,因为它是基于字节码生成...

    JDK动态代理的底层实现原理

    JDK动态代理的底层实现原理

    jdk与cglib动态代理与底层实现

    4. **底层实现原理**: - **JDK代理**:JDK动态代理使用反射和InvocationHandler接口生成一个实现了目标接口的新类。在运行时,这个新类的实例作为代理对象,它的方法调用都会转发到InvocationHandler的`invoke()`...

    java-jdk动态代理的实现demo

    Java JDK 动态代理是一种强大的特性,它允许我们在运行时创建代理类,这些代理类可以扩展或修饰已存在的接口实现。动态代理在很多场景下非常有用,比如日志记录、性能监控、事务管理等,这些功能可以在不修改原始...

    CGLIB 和 JDK生成动态代理类的区别

    CGLIB和JDK动态代理是两种常用的实现方式,它们各有优缺点,适用于不同的场景。下面将详细探讨这两种动态代理的区别。 首先,JDK动态代理主要依赖于`java.lang.reflect.Proxy`类和`java.lang.reflect....

    JDK动态代理proxy

    下面将详细介绍JDK动态代理的工作原理及其实现方式。 ### 1. 动态代理概述 在Java中,动态代理主要由两个类完成:`java.lang.reflect.Proxy` 和 `java.lang.reflect.InvocationHandler`。`Proxy` 类用于创建一个...

    JDK动态代理在EJB3(包括WebService)中的应用

    首先,我们来理解JDK动态代理的工作原理。在Java中,动态代理通过`java.lang.reflect.Proxy`类和`java.lang.reflect.InvocationHandler`接口来实现。Proxy类用于创建一个代理对象,该对象可以作为一个接口的实例,而...

    JavaEE JDK动态代理实现AOP切面功能

    一、JDK动态代理的基本原理 1. `Proxy`类:这个类是Java动态代理的入口,它提供了一种创建代理对象的方式。通过`Proxy.newProxyInstance()`方法,我们可以根据一个接口生成一个实现了该接口的代理对象。 2. `...

    JDK动态代理和Cglib动态代理实例源码

    1. **JDK动态代理实现过程**: - 定义一个接口,被代理类实现该接口。 - 创建`InvocationHandler`实现类,重写`invoke`方法,此方法会在调用被代理类的任何方法时被调用。 - 使用`Proxy.newProxyInstance()`创建...

    模拟JDK动态代理

    在Java编程中,JDK动态代理是一种非常重要的技术,它允许我们在运行时创建对现有接口的代理实现。这种技术在很多场景下都有广泛的应用,比如AOP(面向切面编程)、事务管理、缓存处理等。现在我们来深入探讨一下JDK...

Global site tag (gtag.js) - Google Analytics