Java中动态代理实现原理深究

一、前言

  笔者平时开发使用“动态代理”不多,最近在看设计模式的时候,“动态代理”又在面前晃了几次,所以这次想从源码的角度去分析动态代理的实现原理,以窥探其精妙~

二、正文

2.1 静态代理

   本文源码基于:jdk1.6.0_33

   在正式剖析动态代理的源码之前,我们可以先来看看“静态代理”(就是我们普通的代理模式)的UML图:

  从上图可以看出,代理类“ProxySubject”和被代理类“RealSubject”实现相同接口,并且“ProxySubject”关联“RealSubject”,客户端调用的时候,实际是调用“ProxySubject”,然后“ProxySubject”调用“RealSubject”同名方法,方法的最终实现是由“RealSubject”提供,“ProxySubject”可以实现对“RealSubject”的访问控制,也可以对对应的方法进行“增强”。下面举个简单的例子说明一下:

// Subject
public interface Subject {
    public void doSomething();
}

//ProxySubject
public class ProxySubject implements Subject {
    private Subject realSubject = new RealSubject();
    @Override
    public void doSomething() {
        System.out.println("before doSomething~");
        realSubject.doSomething();
        System.out.println("after doSomething~");
    }

}

//RealSubject
public class RealSubject implements Subject {

    @Override
    public void doSomething() {
        System.out.println("小杜比亚在写博客");
    }

}

//Client
public class Client {

    public static void main(String[] args) {
        Subject subject = new ProxySubject();
        subject.doSomething();
    }

}

//输出
before doSomething~
小杜比亚在写博客
after doSomething~

  那么动态代理和这个静态代理有什么区别?这就体现在一个“动”字,从上面的代码我们知道,静态代理的“代理类”是程序员写好的,而动态代理的“代理类”是在程序运行期间动态生成的~有些刚开始接触Java编程的读者可能会很好奇,Java的类可以动态生成?当然可以,我之前有篇关于“类”加载的博文:深入探讨Java类加载机制里面有写到,程序运行期间,类加载器会将java字节码文件加载进内存,这边的“加载”是从磁盘上加载,java程序只要字节码文件,至于你的来源(网络、或者按照字节码文件格式进行动态生成),人家是不管的。

  直接切入正题,“动态代理”中牵扯到两个类:java.lang.reflect.InvocationHandler和java.lang.reflect.Proxy,我们先看下一个简单的动态代理例子:

 1 //Subject
 2 package com.proxy.main;
 3 public interface Subject {
 4     public void doSomething();
 5 }
 6
 7 //RealSubject
 8 package com.proxy.main;
 9 public class RealSubject implements Subject {
10
11     @Override
12     public void doSomething() {
13         System.out.println("小杜比亚还在写博客,有点儿想玩游戏了,坚持~");
14     }
15 }
16
17 //ProxyHandler
18 package com.proxy.main;
19 import java.lang.reflect.InvocationHandler;
20 import java.lang.reflect.Method;
21
22 public class ProxyHandler implements InvocationHandler {
23     private Object proxiedObj;
24     public ProxyHandler(Object proxiedObj){
25         this.proxiedObj = proxiedObj;
26     }
27     /**
28      * @author caoyg
29      * @date 2017-05-06
30      * @description设置“被代理”对象
31      * @param proxiedObj
32      */
33     public void setProxiedObject(Object proxiedObj){
34         this.proxiedObj = proxiedObj;
35     }
36     @Override
37     public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
38         return method.invoke(proxiedObj, args);
39     }
40
41 }
42
43 //Client
44 package com.proxy.main;
45 import java.lang.reflect.Proxy;
46
47 public class Client {
48
49     public static void main(String[] args) {
50         Subject sb = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
51                                                       new Class[]{Subject.class} ,
52                                                       new ProxyHandler(new RealSubject()));
53         sb.doSomething();
54     }
55
56 }
57
58 //输出
59 小杜比亚还在写博客,有点儿想玩游戏了,坚持~

  上面代码第37行,invoke方法三个参数含义如下:

1 /**
2  该方法负责集中处理动态代理类上的所有方法调用。
3  第一个参数是动态生成的代理类实例,
4  第二个参数是被调用的方法对象
5  第三个方法是方法调用参数。
6  调用处理器根据这三个参数进行预处理或分派到委托类实例上执行
7 */
8 public Object invoke(Object proxy, Method method, Object[] args)
9     throws Throwable;

2.2 动态代理机制

  1、先创建一个InvocationHandler实现类,并且将需要“被代理”的对象传递给它(类似下面代码)

  

2、Proxy通过方法newProxyInstance接收classLoader和一组interfaces(“被代理”对象实现的接口)以及InvocationHandler的实现类实例(以下简称“h”),通过classLoader和interfaces构造动态代理类的Class(下面代码是Proxy的源码部分)

 1 Class cl = getProxyClass(loader, interfaces);
 2 ............
 3 public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)throws IllegalArgumentException
 4     {
 5         //......省略
 6     byte[] proxyClassFile =    ProxyGenerator.generateProxyClass(proxyName, interfaces);
 7     try {
 8         proxyClass = defineClass0(loader, proxyName,
 9         proxyClassFile, 0, proxyClassFile.length);
10     } catch (ClassFormatError e) {
11         /*
12         * A ClassFormatError here means that (barring bugs in the
13         * proxy class generation code) there was some other
14         * invalid aspect of the arguments supplied to the proxy
15         * class creation (such as virtual machine limitations
16         * exceeded).
17         */
18         throw new IllegalArgumentException(e.toString());
19     }
20     //......省略21     return proxyClass;
22 }

  3、Proxy通过反射机制,将传入的h作为参数,调用动态代理对应的构造函数,返回最终的动态代理实例

  在调用动态代理类的方法时,动态代理将方法的调用分派转发给InvocationHandler的invoke方法,InvocationHandler的invoke方法又将方法调用分派给它本身引用的“被代理”类对应的方法。

2.3 动态代理注意点

  1、包:代理接口都是public修饰的,则代理类被定义在顶层包(package为空),如果访问修饰符是默认(default),那么代理类被定义在该接口所在包下面

 1     /*
 2            * Record the package of a non-public proxy interface so that the
 3            * proxy class will be defined in the same package.  Verify that
 4            * all non-public proxy interfaces are in the same package.
 5            */
 6           for (int i = 0; i < interfaces.length; i++) {
 7               int flags = interfaces[i].getModifiers();
 8               if (!Modifier.isPublic(flags)) {
 9                  String name = interfaces[i].getName();
10                  int n = name.lastIndexOf(‘.‘);
11                  String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
12                  if (proxyPkg == null) {
13                    proxyPkg = pkg;
14                  } else if (!pkg.equals(proxyPkg)) {
15                    throw new IllegalArgumentException("non-public interfaces from different packages");
16                  }
17              }
18          }
19
20          if (proxyPkg == null) {    // if no non-public proxy interfaces,
21            proxyPkg = "";        // use the unnamed package
22          }

  2、生成的代理类为public final,不能被继承

3、类名:格式是“$ProxyN”,N是逐一递增的数字,代表Proxy被第N次动态生成的代理类,要注意,对于同一组接口(接口的排列顺序也相同),不会重复创建动态代理类,而是返回一个先前已经创建并缓存了的代理类对象。提高了效率

1      /*
2          * Choose a name for the proxy class to generate.代理类类名生成规则
3          */
4         long num;
5         synchronized (nextUniqueNumberLock) {
6             num = nextUniqueNumber++;
7         }
8         String proxyName = proxyPkg + proxyClassNamePrefix + num;
 1 synchronized (cache) {
 2     /*
 3     * Note that we need not worry about reaping the cache for
 4     * entries with cleared weak references because if a proxy class
 5     * has been garbage collected, its class loader will have been
 6     * garbage collected as well, so the entire cache will be reaped
 7     * from the loaderToCache map.
 8     */
 9     do {
10         Object value = cache.get(key);
11         if (value instanceof Reference) {
12             proxyClass = (Class) ((Reference) value).get();
13         }
14         if (proxyClass != null) {
15             // proxy class already generated: return it
16             return proxyClass;
17         } else if (value == pendingGenerationMarker) {
18             // proxy class being generated: wait for it
19             try {
20                 cache.wait();
21             } catch (InterruptedException e) {
22                 /*
23                 * The class generation that we are waiting for should
24                 * take a small, bounded time, so we can safely ignore
25                 * thread interrupts here.
26                 */
27             }
28             continue;
29         } else {
30             /*
31             * No proxy class for this list of interfaces has been
32             * generated or is being generated, so we will go and
33             * generate it now. Mark it as pending generation.
34             */
35             cache.put(key, pendingGenerationMarker);
36             break;
37         }
38     } while (true);
39 }

  4、类继承关系

  

  Proxy 类是它的父类,这个规则适用于所有由 Proxy 创建的动态代理类。(也算是java动态代理的一处缺陷,java不支持多继承,所以无法实现对class的动态代理,只能对于Interface的代理,cglib解决了这个问题)而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因。

  5、代理类的根类 java.lang.Object 中有三个方法也同样会被分派到调用处理器的 invoke 方法执行,它们是 hashCode,equals 和 toString,代码在反编译中

1 //ProxyGenerator.class
2  private byte[] generateClassFile()
3   {
4     addProxyMethod(hashCodeMethod, Object.class);
5     addProxyMethod(equalsMethod, Object.class);
6     addProxyMethod(toStringMethod, Object.class);
7     .....................
8 }

2.4 Proxy源码分析

  主要关注一些静态变量和两个方法,我们先来看看Proxy中的静态变量:

 1     /** prefix for all proxy class names */
 2    //类名前缀
 3     private final static String proxyClassNamePrefix = "$Proxy";
 4
 5     /** parameter types of a proxy class constructor */
 6    //proxy类构造函数的参数类型,这个在通过反射生成动态代理类的时候用到
 7     private final static Class[] constructorParams = { InvocationHandler.class };
 8
 9     /** maps a class loader to the proxy class cache for that loader */
10     private static Map loaderToCache = new WeakHashMap();
11
12     /** marks that a particular proxy class is currently being generated */
13     private static Object pendingGenerationMarker = new Object();
14
15     /** next number to use for generation of unique proxy class names */
16     //下个proxy的序号
17     private static long nextUniqueNumber = 0;
18     private static Object nextUniqueNumberLock = new Object();
19
20     /** set of all generated proxy classes, for isProxyClass implementation */
21     private static Map proxyClasses = Collections.synchronizedMap(new WeakHashMap());
22
23     /**
24      * the invocation handler for this proxy instance.
25      * @serial
26      */
27     protected InvocationHandler h;

  接下来是两个重要方法:getProxyClass和newProxyInstance,这个newProxyInstance就是我们在前面的动态代理实例里面直接使用的方法,这个方法调用getProxyClass获取动态代理类的Class对象,然后通过反射生成动态代理类实例并返回:

 1  public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException
 2     {
 3     if (h == null) {
 4         throw new NullPointerException();
 5     }
 6
 7     /*
 8      * Look up or generate the designated proxy class.
 9      */
10     //生成动态代理Class
11     Class cl = getProxyClass(loader, interfaces);
12
13     /*
14      * Invoke its constructor with the designated invocation handler.
15      */
16     try {
17         Constructor cons = cl.getConstructor(constructorParams);
18         //通过反射生成动态代理类实例对象,并返回
19         return (Object) cons.newInstance(new Object[] { h });
20     } catch (NoSuchMethodException e) {
21         throw new InternalError(e.toString());
22     } catch (IllegalAccessException e) {
23         throw new InternalError(e.toString());
24     } catch (InstantiationException e) {
25         throw new InternalError(e.toString());
26     } catch (InvocationTargetException e) {
27         throw new InternalError(e.toString());
28     }
29     }

  在Proxy整个源码中,主要工作都集中在方法getProxyClass中:

  1 public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)throws IllegalArgumentException
  2     {
  3     //接口数的限制
  4     if (interfaces.length > 65535) {
  5         throw new IllegalArgumentException("interface limit exceeded");
  6     }
  7
  8     Class proxyClass = null;
  9
 10     /* collect interface names to use as key for proxy class cache */
 11     String[] interfaceNames = new String[interfaces.length];
 12
 13     Set interfaceSet = new HashSet();    // for detecting duplicates
 14     /*下面这个for循环做三项安全验证:
 15      *1、传入的所有接口是否对loader可见,如果不可见,抛出异常
 16      *2、传入的所有”接口“是否真的都是interface,如果不是,抛出异常
 17      *3、传入的所有接口是否有重复,如果有,抛出异常
 18      */
 19     for (int i = 0; i < interfaces.length; i++) {
 20         /*
 21          * Verify that the class loader resolves the name of this
 22          * interface to the same Class object.
 23          */
 24         String interfaceName = interfaces[i].getName();
 25         Class interfaceClass = null;
 26         try {
 27         interfaceClass = Class.forName(interfaceName, false, loader);
 28         } catch (ClassNotFoundException e) {
 29         }
 30         if (interfaceClass != interfaces[i]) {
 31         throw new IllegalArgumentException(
 32             interfaces[i] + " is not visible from class loader");
 33         }
 34
 35         /*
 36          * Verify that the Class object actually represents an
 37          * interface.
 38          */
 39         if (!interfaceClass.isInterface()) {
 40         throw new IllegalArgumentException(
 41             interfaceClass.getName() + " is not an interface");
 42         }
 43
 44         /*
 45          * Verify that this interface is not a duplicate.
 46          */
 47         if (interfaceSet.contains(interfaceClass)) {
 48         throw new IllegalArgumentException(
 49             "repeated interface: " + interfaceClass.getName());
 50         }
 51         interfaceSet.add(interfaceClass);
 52
 53         interfaceNames[i] = interfaceName;
 54     }
 55
 56     /*
 57      * Using string representations of the proxy interfaces as
 58      * keys in the proxy class cache (instead of their Class
 59      * objects) is sufficient because we require the proxy
 60      * interfaces to be resolvable by name through the supplied
 61      * class loader, and it has the advantage that using a string
 62      * representation of a class makes for an implicit weak
 63      * reference to the class.
 64      */
 65     //接口名称列表(List类型)
 66     Object key = Arrays.asList(interfaceNames);
 67
 68     /*
 69      * Find or create the proxy class cache for the class loader.(查询或者创建代理类的缓存,缓存未找到或者已经失效,那么重新创建一个)
 70      */
 71     Map cache;
 72     synchronized (loaderToCache) {
 73         cache = (Map) loaderToCache.get(loader);
 74         if (cache == null) {
 75         cache = new HashMap();
 76         loaderToCache.put(loader, cache);
 77         }
 78         /*
 79          * This mapping will remain valid for the duration of this
 80          * method, without further synchronization, because the mapping
 81          * will only be removed if the class loader becomes unreachable.
 82          */
 83     }
 84
 85     /*
 86      * Look up the list of interfaces in the proxy class cache using
 87      * the key.  This lookup will result in one of three possible
 88      * kinds of values:
 89      *     null, if there is currently no proxy class for the list of
 90      *         interfaces in the class loader,
 91      *     the pendingGenerationMarker object, if a proxy class for the
 92      *         list of interfaces is currently being generated,
 93      *     or a weak reference to a Class object, if a proxy class for
 94      *         the list of interfaces has already been generated.
 95      */
 96     synchronized (cache) {
 97         /*
 98          * Note that we need not worry about reaping the cache for
 99          * entries with cleared weak references because if a proxy class
100          * has been garbage collected, its class loader will have been
101          * garbage collected as well, so the entire cache will be reaped
102          * from the loaderToCache map.
103          */
104         do {
105         //接口名称列表作为key,查找代理类缓存中是否已经存在创建好的动态代理类
106         Object value = cache.get(key);
107         if (value instanceof Reference) {
108             proxyClass = (Class) ((Reference) value).get();
109         }
110         //代理类如果已经创建,直接返回
111         if (proxyClass != null) {
112             // proxy class already generated: return it
113             return proxyClass;
114         } else if (value == pendingGenerationMarker) {//动态代理类还处于创建状态,那么当前线程进入等待
115             // proxy class being generated: wait for it
116             try {
117             cache.wait();
118             } catch (InterruptedException e) {
119             /*
120              * The class generation that we are waiting for should
121              * take a small, bounded time, so we can safely ignore
122              * thread interrupts here.
123              */
124             }
125             continue;//被唤醒之后,进行第二次检查
126         } else {
127             /*
128              * No proxy class for this list of interfaces has been
129              * generated or is being generated, so we will go and
130              * generate it now.  Mark it as pending generation.
131              */
132             /*如果接口名称列表映射的动态代理类还未创建,那么将pendingGenerationMarker先设置到动态代理类的缓存中,
133              *作为key的映射,表示接下来准备要开始动态代理类的创建了,并且退出当前循环
134                              */
135             cache.put(key, pendingGenerationMarker);
136             break;
137         }
138         } while (true);
139     }
140
141     try {
142         String proxyPkg = null;    // package to define proxy class in
143
144         /*
145          * Record the package of a non-public proxy interface so that the
146          * proxy class will be defined in the same package.  Verify that
147          * all non-public proxy interfaces are in the same package.
148          */
149          /*接下来这个循环,就是生成动态代理类的包名。首先校验所有interface是否都是public类型,如果声明为
150                  *public的,那么动态代理类的包名为"",如果存在不止一个interface的接口声明为非public类型(不写修饰符的情况),
151          *那么,所有这些非public访问声明的接口必须在同一个包中,否则抛出错误;如果这些非public访问声明的接口都在同
152          *一个包中,那么动态代理类的包名和这些非public访问声明的接口的包名一致
153          */
154         for (int i = 0; i < interfaces.length; i++) {
155         int flags = interfaces[i].getModifiers();
156         if (!Modifier.isPublic(flags)) {
157             String name = interfaces[i].getName();
158             int n = name.lastIndexOf(‘.‘);
159             String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
160             if (proxyPkg == null) {
161             proxyPkg = pkg;
162             } else if (!pkg.equals(proxyPkg)) {
163             throw new IllegalArgumentException(
164                 "non-public interfaces from different packages");
165             }
166         }
167         }
168
169         if (proxyPkg == null) {    // if no non-public proxy interfaces,
170         proxyPkg = "";        // use the unnamed package
171         }
172
173         {
174         /*
175          * Choose a name for the proxy class to generate.
176          */
177         long num;
178         //生成下一个动态代理类的序号
179         synchronized (nextUniqueNumberLock) {
180             num = nextUniqueNumber++;
181         }
182         //动态代理类的类名:包名+proxyClassNamePrefix + num;
183         String proxyName = proxyPkg + proxyClassNamePrefix + num;
184         /*
185          * Verify that the class loader hasn‘t already
186          * defined a class with the chosen name.
187          */
188
189         /*
190          * Generate the specified proxy class.
191          */
192         //这个方法别人说有点儿复杂,反编译进去看确实挺复杂,这边笔者解释不了,这边就是生成动态代理类的字节
193         byte[] proxyClassFile =    ProxyGenerator.generateProxyClass(
194             proxyName, interfaces);
195         try {
196             proxyClass = defineClass0(loader, proxyName,
197             proxyClassFile, 0, proxyClassFile.length);
198         } catch (ClassFormatError e) {
199             /*
200              * A ClassFormatError here means that (barring bugs in the
201              * proxy class generation code) there was some other
202              * invalid aspect of the arguments supplied to the proxy
203              * class creation (such as virtual machine limitations
204              * exceeded).
205              */
206             throw new IllegalArgumentException(e.toString());
207         }
208         }
209         // add to set of all generated proxy classes, for isProxyClass
210         proxyClasses.put(proxyClass, null);
211
212     } finally {
213         /*
214          * We must clean up the "pending generation" state of the proxy
215          * class cache entry somehow.  If a proxy class was successfully
216          * generated, store it in the cache (with a weak reference);
217          * otherwise, remove the reserved entry.  In all cases, notify
218          * all waiters on reserved entries in this cache.
219          */
220         synchronized (cache) {
221         if (proxyClass != null) {
222             /*如果动态代理类创建成功,那么将动态代理类缓存中key对应的值更新成new WeakReference(proxyClass),原先
223              *设置的是pendingGenerationMarker
224              */
225             cache.put(key, new WeakReference(proxyClass));
226         } else {
227             //如果创建不成功,那么将key对应的映射移除
228             cache.remove(key);
229         }
230         //不管创建成功不成功,将阻塞在代理类缓存上面的线程唤醒
231         cache.notifyAll();
232         }
233     }
234     return proxyClass;
235     }

  以上内容已经大致将动态代理的内部实现交代清楚,下面的程序将动态代理的实例写入class文件,然后反编译出来看下,动态代理类的实例到底长什么样:

  生成动态代理类的Class文件代码:

 1 package com.proxy.main;
 2
 3 import java.io.FileOutputStream;
 4 import java.lang.reflect.Proxy;
 5
 6 import sun.misc.ProxyGenerator;
 7
 8 public class Client {
 9
10     public static void main(String[] args) {
11         Subject sb = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
12                                                       new Class[]{Subject.class} ,
13                                                       new ProxyHandler(new RealSubject()));
14         sb.doSomething();
15         createProxyClassFile();
16     }
17
18     public static void createProxyClassFile(){
19         try{
20             String proxyName = "MyProxy";
21             byte[] data = ProxyGenerator.generateProxyClass(proxyName, new Class[]{Subject.class});
22             FileOutputStream out = new FileOutputStream( proxyName + ".class" );
23             out.write(data);
24             out.close();
25         }
26         catch(Exception e){
27             e.printStackTrace();
28         }
29     }
30
31 }

  动态代理类反编译出来的代码:

  1 //因为传进去的interface数据中,所有interface的声明都是public,所以,动态代理类的包名为""
  2 import com.proxy.main.Subject;
  3 import java.lang.reflect.InvocationHandler;
  4 import java.lang.reflect.Method;
  5 import java.lang.reflect.Proxy;
  6 import java.lang.reflect.UndeclaredThrowableException;
  7 //继承自Proxy
  8 public final class MyProxy extends Proxy
  9   implements Subject
 10 {
 11   private static Method m1;
 12   private static Method m0;
 13   private static Method m3;
 14   private static Method m2;
 15
 16   public MyProxy(InvocationHandler paramInvocationHandler)
 17     throws
 18   {
 19     super(paramInvocationHandler);
 20   }
 21
 22   public final boolean equals(Object paramObject)
 23     throws
 24   {
 25     try
 26     {
 27       return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
 28     }
 29     catch (RuntimeException localRuntimeException)
 30     {
 31       throw localRuntimeException;
 32     }
 33     catch (Throwable localThrowable)
 34     {
 35     }
 36     throw new UndeclaredThrowableException(localThrowable);
 37   }
 38
 39   public final int hashCode()
 40     throws
 41   {
 42     try
 43     {
 44       return ((Integer)this.h.invoke(this, m0, null)).intValue();
 45     }
 46     catch (RuntimeException localRuntimeException)
 47     {
 48       throw localRuntimeException;
 49     }
 50     catch (Throwable localThrowable)
 51     {
 52     }
 53     throw new UndeclaredThrowableException(localThrowable);
 54   }
 55
 56   public final void doSomething()
 57     throws
 58   {
 59     try
 60     {
 61       this.h.invoke(this, m3, null);
 62       return;
 63     }
 64     catch (RuntimeException localRuntimeException)
 65     {
 66       throw localRuntimeException;
 67     }
 68     catch (Throwable localThrowable)
 69     {
 70     }
 71     throw new UndeclaredThrowableException(localThrowable);
 72   }
 73
 74   public final String toString()
 75     throws
 76   {
 77     try
 78     {
 79       return (String)this.h.invoke(this, m2, null);
 80     }
 81     catch (RuntimeException localRuntimeException)
 82     {
 83       throw localRuntimeException;
 84     }
 85     catch (Throwable localThrowable)
 86     {
 87     }
 88     throw new UndeclaredThrowableException(localThrowable);
 89   }
 90
 91   static
 92   {
 93     try
 94     {
 95       m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
 96       m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
 97       m3 = Class.forName("com.proxy.main.Subject").getMethod("doSomething", new Class[0]);
 98       m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
 99       return;
100     }
101     catch (NoSuchMethodException localNoSuchMethodException)
102     {
103       throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
104     }
105     catch (ClassNotFoundException localClassNotFoundException)
106     {
107     }
108     throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
109   }
110 }

三、链接

http://blog.csdn.net/scplove/article/details/52451899

http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html

四、联系本人

  为方便没有博客园账号的读者交流,特意建立一个企鹅群,读者如果有对博文不明之处,欢迎加群交流:261746360,小杜比亚-博客园

时间: 2024-10-24 13:29:28

Java中动态代理实现原理深究的相关文章

java中动态代理实现机制

JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterface{ int sub(int a, int b); } 实现类 class Arithmetic implements AddInterface, SubInterface{ @Override public int sub(int a, int b) { return a-b; } @Override public i

java中动态代理

一.在java中怎样实现动态代理 1.我们要有一个接口,还要有一个接口的实现类,而这个实现类呢就是我们要代理的对象 接口: 1 package org.dynamicproxy.test; 2 3 public interface UserDao { 4 public void addUser(User user); 5 } 接口的实现类(即要代理的对象): 1 package org.dynamicproxy.test; 2 3 public class UserDaoMysqlImpl im

java中动态代理的实现

动态代理的实现 使用的模式:代理模式.代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问.类似租房的中介. 两种动态代理:(1)jdk动态代理,jdk动态代理是由Java内部的反射机制来实现的,目标类基于统一的接口(InvocationHandler)(2)cglib动态代理,cglib动态代理底层则是借助asm来实现的,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势. 主要应用的框架:Spring中的AOP,Struts2中的拦截器 具体实现: 1.定义接口

Java中动态代理技术生成的类与原始类的区别 (转)

用动态代理的时候,对它新生成的类长什么样子感到好奇.有幸通过一些资料消除了心里的疑惑. 平时工作使用的Spring框架里面有一个AOP(面向切面)的机制,只知道它是把类重新生成了一遍,在切面上加上了后来定义的逻辑.这样就达到了动态的在原有类上增加一些功能.比如日志打印,拦截信息等. 这里只关心动态代理技术生成新的类,先不管虚拟机是如何去生成类,用了什么字节码生成技术,怎么产生字节码等这一系列动作.现在只关心最后生成的新类长什么样,它和老类有什么区别.为了获取到生成后的代理类的字节码并且反编译成我

Java中动态代理方式:

JDK中生成代理对象的API 代理类所在包:java.lang.reflect.ProxyJDK实现代理只需要使用newProxyInstance方法,但是该方法需要接收三个参数,完整的写法是: static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h ) 注意该方法是在Proxy类中是静态方法,且接收的三个参数依次为: ClassLoader loader,:指定当

java高级----&gt;Java动态代理的原理

Java动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.下面我们开始动态代理的学习. 目录导航   动态代理的简要说明 简单的Java代理 Java的动态代理 Java动态代理的原理 友情链接 动态代理的简要说明 在java的动态代理机制中,有两个重要的类或接口,一个是 In

java的动态代理机制详解

在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于 Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是 java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Cla

JAVA静态&amp;动态代理

具体场景 为了使代理类和被代理类对第三方有相同的函数,代理类和被代理类一般实现一个公共的interface,该interface定义如下 public interface Calculator { public Integer add(Integer num1, Integer num2); public Integer minus(Integer num1, Integer num2); } 被代理类定义如下 public class CalculatorImpl implements Cal

代理模式 &amp; Java原生动态代理技术 &amp; CGLib动态代理技术

第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.(其实就是在代理类中关联一个委托类的实例,然后在代理类中进行包装). UML图如下: 第二部分.在Java中实现代理模式  按照代理的创建时期,代理类可以分