Java JDK 動態代理(AOP)使用及實現原理分析

1、什麼是代理?

代理是一種經常使用的設計模式,其目的就是爲其餘對象提供一個代理以控制對某個對象的訪問。代理類負責爲委託類預處理消息,過濾消息並轉發消息,以及進行消息被委託類執行後的後續處理。

代理模式UML圖:



簡單結構示意圖:



爲了保持行爲的一致性,代理類和委託類一般會實現相同的接口,因此在訪問者看來二者沒有絲毫的區別。經過代理類這中間一層,能有效控制對委託類對象的直接訪問,也能夠很好地隱藏和保護委託類對象,同時也爲實施不一樣控制策略預留了空間,從而在設計上得到了更大的靈活性。Java 動態代理機制以巧妙的方式近乎完美地實踐了代理模式的設計理念。

2、Java 動態代理類 

Java動態代理類位於java.lang.reflect包下,通常主要涉及到如下兩個類:

(1)Interface InvocationHandler:該接口中僅定義了一個方法

[java] view plain copy



publicobject invoke(Object obj,Method method, Object[] args)  
在實際使用時,第一個參數obj通常是指代理類,method是被代理的方法,如上例中的request(),args爲該方法的參數數組。這個抽象方法在代理類中動態實現。

(2)Proxy:該類即爲動態代理類,其中主要包含如下內容:



protected Proxy(InvocationHandler h):構造函數,用於給內部的h賦值。

static Class getProxyClass (ClassLoaderloader, Class[] interfaces):得到一個代理類,其中loader是類裝載器,interfaces是真實類所擁有的所有接口的數組。

static Object newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h):返回代理類的一個實例,返回後的代理類能夠看成被代理類使用(可以使用被代理類的在Subject接口中聲明過的方法)



所謂DynamicProxy是這樣一種class:它是在運行時生成的class,在生成它時你必須提供一組interface給它,而後該class就宣稱它實現了這些 interface。你固然能夠把該class的實例看成這些interface中的任何一個來用。固然,這個DynamicProxy其實就是一個Proxy,它不會替你做實質性的工做,在生成它的實例時你必須提供一個handler,由它接管實際的工做。



在使用動態代理類時,咱們必須實現InvocationHandler接口



經過這種方式,被代理的對象(RealSubject)能夠在運行時動態改變,須要控制的接口(Subject接口)能夠在運行時改變,控制的方式(DynamicSubject類)也能夠動態改變,從而實現了很是靈活的動態代理關係。

動態代理步驟:
1.建立一個實現接口InvocationHandler的類,它必須實現invoke方法
2.建立被代理的類以及接口
3.經過Proxy的靜態方法
newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h)建立一個代理
4.經過代理調用方法



3、JDK的動態代理怎麼使用?

一、須要動態代理的接口:



[java] view plain copy



package jiankunking;  
  
/** 
 * 須要動態代理的接口 
 */  
public interface Subject  
{  
    /** 
     * 你好 
     * 
     * @param name 
     * @return 
     */  
    public String SayHello(String name);  
  
    /** 
     * 再見 
     * 
     * @return 
     */  
    public String SayGoodBye();  
}  

二、須要代理的實際對象





[java] view plain copy



package jiankunking;  
  
/** 
 * 實際對象 
 */  
public class RealSubject implements Subject  
{  
  
    /** 
     * 你好 
     * 
     * @param name 
     * @return 
     */  
    public String SayHello(String name)  
    {  
        return "hello " + name;  
    }  
  
    /** 
     * 再見 
     * 
     * @return 
     */  
    public String SayGoodBye()  
    {  
        return " good bye ";  
    }  
}  

三、調用處理器實現類(有木有感受這裏就是傳說中的AOP啊)





[java] view plain copy



package jiankunking;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
  
  
/** 
 * 調用處理器實現類 
 * 每次生成動態代理類對象時都須要指定一個實現了該接口的調用處理器對象 
 */  
public class InvocationHandlerImpl implements InvocationHandler  
{  
  
    /** 
     * 這個就是咱們要代理的真實對象 
     */  
    private Object subject;  
  
    /** 
     * 構造方法,給咱們要代理的真實對象賦初值 
     * 
     * @param subject 
     */  
    public InvocationHandlerImpl(Object subject)  
    {  
        this.subject = subject;  
    }  
  
    /** 
     * 該方法負責集中處理動態代理類上的全部方法調用。 
     * 調用處理器根據這三個參數進行預處理或分派到委託類實例上反射執行 
     * 
     * @param proxy  代理類實例 
     * @param method 被調用的方法對象 
     * @param args   調用參數 
     * @return 
     * @throws Throwable 
     */  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable  
    {  
        //在代理真實對象前咱們能夠添加一些本身的操做  
        System.out.println("在調用以前,我要乾點啥呢?");  
  
        System.out.println("Method:" + method);  
  
        //當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用  
        Object returnValue = method.invoke(subject, args);  
  
        //在代理真實對象後咱們也能夠添加一些本身的操做  
        System.out.println("在調用以後,我要乾點啥呢?");  
  
        return returnValue;  
    }  
}  
四、測試



[java] view plain copy



package jiankunking;  
  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Proxy;  
  
/** 
 * 動態代理演示 
 */  
public class DynamicProxyDemonstration  
{  
    public static void main(String[] args)  
    {  
        //代理的真實對象  
        Subject realSubject = new RealSubject();  
          
        /** 
         * InvocationHandlerImpl 實現了 InvocationHandler 接口,並能實現方法調用從代理類到委託類的分派轉發 
         * 其內部一般包含指向委託類實例的引用,用於真正執行分派轉發過來的方法調用. 
         * 即:要代理哪一個真實對象,就將該對象傳進去,最後是經過該真實對象來調用其方法 
         */  
        InvocationHandler handler = new InvocationHandlerImpl(realSubject);  
  
        ClassLoader loader = realSubject.getClass().getClassLoader();  
        Class[] interfaces = realSubject.getClass().getInterfaces();  
        /** 
         * 該方法用於爲指定類裝載器、一組接口及調用處理器生成動態代理類實例 
         */  
        Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);  
  
        System.out.println("動態代理對象的類型:"+subject.getClass().getName());  
  
        String hello = subject.SayHello("jiankunking");  
        System.out.println(hello);  
//        String goodbye = subject.SayGoodBye();  
//        System.out.println(goodbye);  
    }  
  
}  






五、輸出結果以下:





演示demo下載地址:http://download.csdn.net/detail/xunzaosiyecao/9597388

4、動態代理怎麼實現的?

從使用代碼中能夠看出,關鍵點在:

[java] view plain copy



Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);  
經過跟蹤提示代碼能夠看出:當代理對象調用真實對象的方法時,其會自動的跳轉到代理對象關聯的handler對象的invoke方法來進行調用。

也就是說,當代碼執行到:

subject.SayHello("jiankunking")這句話時,會自動調用InvocationHandlerImpl的invoke方法。這是爲啥呢?



======================橫線之間的是代碼跟分析的過程,不想看的朋友能夠直接看結論=====================================

如下代碼來自:JDK1.8.0_92

既然生成代理對象是用的Proxy類的靜態方newProxyInstance,那麼咱們就去它的源碼裏看一下它到底都作了些什麼? 

[java] view plain copy



/** 
 * Returns an instance of a proxy class for the specified interfaces 
 * that dispatches method invocations to the specified invocation 
 * handler. 
 * 
 * <p>{@code Proxy.newProxyInstance} throws 
 * {@code IllegalArgumentException} for the same reasons that 
 * {@code Proxy.getProxyClass} does. 
 * 
 * @param   loader the class loader to define the proxy class 
 * @param   interfaces the list of interfaces for the proxy class 
 *          to implement 
 * @param   h the invocation handler to dispatch method invocations to 
 * @return  a proxy instance with the specified invocation handler of a 
 *          proxy class that is defined by the specified class loader 
 *          and that implements the specified interfaces 
 * @throws  IllegalArgumentException if any of the restrictions on the 
 *          parameters that may be passed to {@code getProxyClass} 
 *          are violated 
 * @throws  SecurityException if a security manager, <em>s</em>, is present 
 *          and any of the following conditions is met: 
 *          <ul> 
 *          <li> the given {@code loader} is {@code null} and 
 *               the caller's class loader is not {@code null} and the 
 *               invocation of {@link SecurityManager#checkPermission 
 *               s.checkPermission} with 
 *               {@code RuntimePermission("getClassLoader")} permission 
 *               denies access;</li> 
 *          <li> for each proxy interface, {@code intf}, 
 *               the caller's class loader is not the same as or an 
 *               ancestor of the class loader for {@code intf} and 
 *               invocation of {@link SecurityManager#checkPackageAccess 
 *               s.checkPackageAccess()} denies access to {@code intf};</li> 
 *          <li> any of the given proxy interfaces is non-public and the 
 *               caller class is not in the same {@linkplain Package runtime package} 
 *               as the non-public interface and the invocation of 
 *               {@link SecurityManager#checkPermission s.checkPermission} with 
 *               {@code ReflectPermission("newProxyInPackage.{package name}")} 
 *               permission denies access.</li> 
 *          </ul> 
 * @throws  NullPointerException if the {@code interfaces} array 
 *          argument or any of its elements are {@code null}, or 
 *          if the invocation handler, {@code h}, is 
 *          {@code null} 
 */  
@CallerSensitive   
public static Object newProxyInstance(ClassLoader loader,  
                                          Class<?>[] interfaces,  
                                          InvocationHandler h)  
        throws IllegalArgumentException  
    {  
        //檢查h 不爲空,不然拋異常  
        Objects.requireNonNull(h);  
  
        final Class<?>[] intfs = interfaces.clone();  
        final SecurityManager sm = System.getSecurityManager();  
        if (sm != null) {  
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);  
        }  
  
        /* 
         * 得到與指定類裝載器和一組接口相關的代理類類型對象 
         */  
        Class<?> cl = getProxyClass0(loader, intfs);  
  
        /* 
         * 經過反射獲取構造函數對象並生成代理類實例 
         */  
        try {  
            if (sm != null) {  
                checkNewProxyPermission(Reflection.getCallerClass(), cl);  
            }  
            //獲取代理對象的構造方法(也就是$Proxy0(InvocationHandler h))   
            final Constructor<?> cons = cl.getConstructor(constructorParams);  
            final InvocationHandler ih = h;  
            if (!Modifier.isPublic(cl.getModifiers())) {  
                AccessController.doPrivileged(new PrivilegedAction<Void>() {  
                    public Void run() {  
                        cons.setAccessible(true);  
                        return null;  
                    }  
                });  
            }  
            //生成代理類的實例並把InvocationHandlerImpl的實例傳給它的構造方法  
            return cons.newInstance(new Object[]{h});  
        } catch (IllegalAccessException|InstantiationException e) {  
            throw new InternalError(e.toString(), e);  
        } catch (InvocationTargetException e) {  
            Throwable t = e.getCause();  
            if (t instanceof RuntimeException) {  
                throw (RuntimeException) t;  
            } else {  
                throw new InternalError(t.toString(), t);  
            }  
        } catch (NoSuchMethodException e) {  
            throw new InternalError(e.toString(), e);  
        }  
    }  



咱們再進去getProxyClass0方法看一下:

[java] view plain copy



/** 
    * Generate a proxy class.  Must call the checkProxyAccess method 
    * to perform permission checks before calling this. 
    */  
   private static Class<?> getProxyClass0(ClassLoader loader,  
                                          Class<?>... interfaces) {  
       if (interfaces.length > 65535) {  
           throw new IllegalArgumentException("interface limit exceeded");  
       }  
  
       // If the proxy class defined by the given loader implementing  
       // the given interfaces exists, this will simply return the cached copy;  
       // otherwise, it will create the proxy class via the ProxyClassFactory  
       return proxyClassCache.get(loader, interfaces);  
   }  
真相仍是沒有來到,繼續,看一下proxyClassCache

[java] view plain copy



/** 
     * a cache of proxy classes 
     */  
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>  
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());  
奧,原來用了一下緩存啊

那麼它對應的get方法啥樣呢?

[java] view plain copy



/** 
    * Look-up the value through the cache. This always evaluates the 
    * {@code subKeyFactory} function and optionally evaluates 
    * {@code valueFactory} function if there is no entry in the cache for given 
    * pair of (key, subKey) or the entry has already been cleared. 
    * 
    * @param key       possibly null key 
    * @param parameter parameter used together with key to create sub-key and 
    *                  value (should not be null) 
    * @return the cached value (never null) 
    * @throws NullPointerException if {@code parameter} passed in or 
    *                              {@code sub-key} calculated by 
    *                              {@code subKeyFactory} or {@code value} 
    *                              calculated by {@code valueFactory} is null. 
    */  
   public V get(K key, P parameter) {  
       Objects.requireNonNull(parameter);  
  
       expungeStaleEntries();  
  
       Object cacheKey = CacheKey.valueOf(key, refQueue);  
  
       // lazily install the 2nd level valuesMap for the particular cacheKey  
       ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);  
       if (valuesMap == null) {  
        //putIfAbsent這個方法在key不存在的時候加入一個值,若是key存在就不放入  
           ConcurrentMap<Object, Supplier<V>> oldValuesMap  
               = map.putIfAbsent(cacheKey,  
                                 valuesMap = new ConcurrentHashMap<>());  
           if (oldValuesMap != null) {  
               valuesMap = oldValuesMap;  
           }  
       }  
  
       // create subKey and retrieve the possible Supplier<V> stored by that  
       // subKey from valuesMap  
       Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));  
       Supplier<V> supplier = valuesMap.get(subKey);  
       Factory factory = null;  
  
       while (true) {  
           if (supplier != null) {  
               // supplier might be a Factory or a CacheValue<V> instance  
               V value = supplier.get();  
               if (value != null) {  
                   return value;  
               }  
           }  
           // else no supplier in cache  
           // or a supplier that returned null (could be a cleared CacheValue  
           // or a Factory that wasn't successful in installing the CacheValue)  
  
           // lazily construct a Factory  
           if (factory == null) {  
               factory = new Factory(key, parameter, subKey, valuesMap);  
           }  
  
           if (supplier == null) {                
               supplier = valuesMap.putIfAbsent(subKey, factory);  
               if (supplier == null) {  
                   // successfully installed Factory  
                   supplier = factory;  
               }  
               // else retry with winning supplier  
           } else {  
               if (valuesMap.replace(subKey, supplier, factory)) {  
                   // successfully replaced  
                   // cleared CacheEntry / unsuccessful Factory  
                   // with our Factory  
                   supplier = factory;  
               } else {  
                   // retry with current supplier  
                   supplier = valuesMap.get(subKey);  
               }  
           }  
       }  
   }  

咱們能夠看到它調用了 supplier.get(); 獲取動態代理類,其中supplier是Factory,這個類定義在WeakCach的內部。

來瞅瞅,get裏面又作了什麼?

[java] view plain copy



public synchronized V get() { // serialize access  
           // re-check  
           Supplier<V> supplier = valuesMap.get(subKey);  
           if (supplier != this) {  
               // something changed while we were waiting:  
               // might be that we were replaced by a CacheValue  
               // or were removed because of failure ->  
               // return null to signal WeakCache.get() to retry  
               // the loop  
               return null;  
           }  
           // else still us (supplier == this)  
  
           // create new value  
           V value = null;  
           try {  
               value = Objects.requireNonNull(valueFactory.apply(key, parameter));  
           } finally {  
               if (value == null) { // remove us on failure  
                   valuesMap.remove(subKey, this);  
               }  
           }  
           // the only path to reach here is with non-null value  
           assert value != null;  
  
           // wrap value with CacheValue (WeakReference)  
           CacheValue<V> cacheValue = new CacheValue<>(value);  
  
           // try replacing us with CacheValue (this should always succeed)  
           if (valuesMap.replace(subKey, this, cacheValue)) {  
               // put also in reverseMap  
               reverseMap.put(cacheValue, Boolean.TRUE);  
           } else {  
               throw new AssertionError("Should not reach here");  
           }  
  
           // successfully replaced us with new CacheValue -> return the value  
           // wrapped by it  
           return value;  
       }  
   }  

發現重點仍是木有出現,但咱們能夠看到它調用了valueFactory.apply(key, parameter)方法:

[java] view plain copy



/** 
    * A factory function that generates, defines and returns the proxy class given 
    * the ClassLoader and array of interfaces. 
    */  
   private static final class ProxyClassFactory  
       implements BiFunction<ClassLoader, Class<?>[], Class<?>>  
   {  
       // prefix for all proxy class names  
       private static final String proxyClassNamePrefix = "$Proxy";  
  
       // next number to use for generation of unique proxy class names  
       private static final AtomicLong nextUniqueNumber = new AtomicLong();  
  
       @Override  
       public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {  
  
           Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);  
           for (Class<?> intf : interfaces) {  
               /* 
                * Verify that the class loader resolves the name of this 
                * interface to the same Class object. 
                */  
               Class<?> interfaceClass = null;  
               try {  
                   interfaceClass = Class.forName(intf.getName(), false, loader);  
               } catch (ClassNotFoundException e) {  
               }  
               if (interfaceClass != intf) {  
                   throw new IllegalArgumentException(  
                       intf + " is not visible from class loader");  
               }  
               /* 
                * Verify that the Class object actually represents an 
                * interface. 
                */  
               if (!interfaceClass.isInterface()) {  
                   throw new IllegalArgumentException(  
                       interfaceClass.getName() + " is not an interface");  
               }  
               /* 
                * Verify that this interface is not a duplicate. 
                */  
               if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {  
                   throw new IllegalArgumentException(  
                       "repeated interface: " + interfaceClass.getName());  
               }  
           }  
  
           String proxyPkg = null;     // package to define proxy class in  
           int accessFlags = Modifier.PUBLIC | Modifier.FINAL;  
  
           /* 
            * Record the package of a non-public proxy interface so that the 
            * proxy class will be defined in the same package.  Verify that 
            * all non-public proxy interfaces are in the same package. 
            */  
           for (Class<?> intf : interfaces) {  
               int flags = intf.getModifiers();  
               if (!Modifier.isPublic(flags)) {  
                   accessFlags = Modifier.FINAL;  
                   String name = intf.getName();  
                   int n = name.lastIndexOf('.');  
                   String pkg = ((n == -1) ? "" : name.substring(0, n + 1));  
                   if (proxyPkg == null) {  
                       proxyPkg = pkg;  
                   } else if (!pkg.equals(proxyPkg)) {  
                       throw new IllegalArgumentException(  
                           "non-public interfaces from different packages");  
                   }  
               }  
           }  
  
           if (proxyPkg == null) {  
               // if no non-public proxy interfaces, use com.sun.proxy package  
               proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";  
           }  
  
           /* 
            * Choose a name for the proxy class to generate. 
            */  
           long num = nextUniqueNumber.getAndIncrement();  
           String proxyName = proxyPkg + proxyClassNamePrefix + num;  
  
           /* 
            * Generate the specified proxy class. 
            */  
           byte[] proxyClassFile = ProxyGenerator.generateProxyClass(  
               proxyName, interfaces, accessFlags);  
           try {  
               return defineClass0(loader, proxyName,  
                                   proxyClassFile, 0, proxyClassFile.length);  
           } catch (ClassFormatError e) {  
               /* 
                * A ClassFormatError here means that (barring bugs in the 
                * proxy class generation code) there was some other 
                * invalid aspect of the arguments supplied to the proxy 
                * class creation (such as virtual machine limitations 
                * exceeded). 
                */  
               throw new IllegalArgumentException(e.toString());  
           }  
       }  
   }  
經過看代碼終於找到了重點:

[java] view plain copy



//生成字節碼  
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);  
那麼接下來咱們也使用測試一下,使用這個方法生成的字節碼是個什麼樣子:
[java] view plain copy



package jiankunking;  
  
import sun.misc.ProxyGenerator;  
  
import java.io.File;  
import java.io.FileNotFoundException;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Proxy;  
  
/** 
 * 動態代理演示 
 */  
public class DynamicProxyDemonstration  
{  
    public static void main(String[] args)  
    {  
        //代理的真實對象  
        Subject realSubject = new RealSubject();  
  
        /** 
         * InvocationHandlerImpl 實現了 InvocationHandler 接口,並能實現方法調用從代理類到委託類的分派轉發 
         * 其內部一般包含指向委託類實例的引用,用於真正執行分派轉發過來的方法調用. 
         * 即:要代理哪一個真實對象,就將該對象傳進去,最後是經過該真實對象來調用其方法 
         */  
        InvocationHandler handler = new InvocationHandlerImpl(realSubject);  
  
        ClassLoader loader = handler.getClass().getClassLoader();  
        Class[] interfaces = realSubject.getClass().getInterfaces();  
        /** 
         * 該方法用於爲指定類裝載器、一組接口及調用處理器生成動態代理類實例 
         */  
        Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);  
  
        System.out.println("動態代理對象的類型:"+subject.getClass().getName());  
  
        String hello = subject.SayHello("jiankunking");  
        System.out.println(hello);  
        // 將生成的字節碼保存到本地,  
        createProxyClassFile();  
    }  
    private static void createProxyClassFile(){  
        String name = "ProxySubject";  
        byte[] data = ProxyGenerator.generateProxyClass(name,new Class[]{Subject.class});  
        FileOutputStream out =null;  
        try {  
            out = new FileOutputStream(name+".class");  
            System.out.println((new File("hello")).getAbsolutePath());  
            out.write(data);  
        } catch (FileNotFoundException e) {  
            e.printStackTrace();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }finally {  
            if(null!=out) try {  
                out.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
  
}  
能夠看一下這裏代理對象的類型:



咱們用jd-jui 工具將生成的字節碼反編譯:

[java] view plain copy



import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
import java.lang.reflect.Proxy;  
import java.lang.reflect.UndeclaredThrowableException;  
import jiankunking.Subject;  
  
public final class ProxySubject  
  extends Proxy  
  implements Subject  
{  
  private static Method m1;  
  private static Method m3;  
  private static Method m4;  
  private static Method m2;  
  private static Method m0;  
    
  public ProxySubject(InvocationHandler paramInvocationHandler)  
  {  
    super(paramInvocationHandler);  
  }  
    
  public final boolean equals(Object paramObject)  
  {  
    try  
    {  
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();  
    }  
    catch (Error|RuntimeException localError)  
    {  
      throw localError;  
    }  
    catch (Throwable localThrowable)  
    {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
    
  public final String SayGoodBye()  
  {  
    try  
    {  
      return (String)this.h.invoke(this, m3, null);  
    }  
    catch (Error|RuntimeException localError)  
    {  
      throw localError;  
    }  
    catch (Throwable localThrowable)  
    {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
    
  public final String SayHello(String paramString)  
  {  
    try  
    {  
      return (String)this.h.invoke(this, m4, new Object[] { paramString });  
    }  
    catch (Error|RuntimeException localError)  
    {  
      throw localError;  
    }  
    catch (Throwable localThrowable)  
    {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
    
  public final String toString()  
  {  
    try  
    {  
      return (String)this.h.invoke(this, m2, null);  
    }  
    catch (Error|RuntimeException localError)  
    {  
      throw localError;  
    }  
    catch (Throwable localThrowable)  
    {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
    
  public final int hashCode()  
  {  
    try  
    {  
      return ((Integer)this.h.invoke(this, m0, null)).intValue();  
    }  
    catch (Error|RuntimeException localError)  
    {  
      throw localError;  
    }  
    catch (Throwable localThrowable)  
    {  
      throw new UndeclaredThrowableException(localThrowable);  
    }  
  }  
    
  static  
  {  
    try  
    {  
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });  
      m3 = Class.forName("jiankunking.Subject").getMethod("SayGoodBye", new Class[0]);  
      m4 = Class.forName("jiankunking.Subject").getMethod("SayHello", new Class[] { Class.forName("java.lang.String") });  
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);  
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);  
      return;  
    }  
    catch (NoSuchMethodException localNoSuchMethodException)  
    {  
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());  
    }  
    catch (ClassNotFoundException localClassNotFoundException)  
    {  
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());  
    }  
  }  
}  

這就是最終真正的代理類,它繼承自Proxy並實現了咱們定義的Subject接口
也就是說:

[java] view plain copy



Subject subject = (Subject) Proxy.newProxyInstance(loader, interfaces, handler);  
這裏的subject實際是這個類的一個實例,那麼咱們調用它的:

[java] view plain copy



public final String SayHello(String paramString)  
就是調用咱們定義的InvocationHandlerImpl的 invoke方法:



======================橫線之間的是代碼跟分析的過程,不想看的朋友能夠直接看結論=====================================

5、結論

到了這裏,終於解答了:
subject.SayHello("jiankunking")這句話時,爲何會自動調用InvocationHandlerImpl的invoke方法?

由於JDK生成的最終真正的代理類,它繼承自Proxy並實現了咱們定義的Subject接口,在實現Subject接口方法的內部,經過反射調用了
InvocationHandlerImpl的invoke方法。

包含生成本地class文件的demo:
http://download.csdn.net/detail/xunzaosiyecao/9597474
https://github.com/JianKunKing/DynamicProxyDemo

經過分析代碼能夠看出Java 動態代理,具體有以下四步驟:
經過實現 InvocationHandler 接口建立本身的調用處理器;
經過爲 Proxy 類指定 ClassLoader 對象和一組 interface 來建立動態代理類;
經過反射機制得到動態代理類的構造函數,其惟一參數類型是調用處理器接口類型;
經過構造函數建立動態代理類實例,構造時調用處理器對象做爲參數被傳入。




做者:jiankunking 出處:http://blog.csdn.net/jiankunking

我的微信公衆號:









本文參考過:

http://www.2cto.com/kf/201608/533663.html

http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html
相關文章
相關標籤/搜索