jdk動態代理源碼分析

jdk動態代理源碼分析

源碼探索代理類如何產生以及invoke的是如何如何調用的

一、 調用Proxy.newProxyInstance()

 public Object newProxyInstance(Object targetObject){  
        this.targetObject=targetObject;  
        //該方法用於爲指定類裝載器、一組接口及調用處理器生成動態代理類實例    
        //第一個參數指定產生代理對象的類加載器,需要將其指定爲和目標對象同一個類加載器  
        //第二個參數要實現和目標對象一樣的接口,所以只需要拿到目標對象的實現接口  
        //第三個參數表明這些被攔截的方法在被攔截時需要執行哪個InvocationHandler的invoke方法  
        //根據傳入的目標返回一個代理對象  
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
                targetObject.getClass().getInterfaces(),this);  
    }  

二、調用getProxyClass0()方法

 public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

三、調用proxyClassCache,從緩存中獲取

 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);
    }

四、ProxyClassFactory工廠的產生緩存

 /**
     * a cache of proxy classes
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

五、ProxyClassFactory生成字節碼文件

 /**
     * 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);
            }

六、ProxyGenerator.generateProxyClass 生成代理實現類

public static byte[] generateProxyClass(final String name,  
                                           Class[] interfaces)  
   {  
       ProxyGenerator gen = new ProxyGenerator(name, interfaces);  
       final byte[] classFile = gen.generateClassFile();  
  
    // 如果saveGeneratedFiles的值爲true,則會把所生成的代理類的字節碼保存到硬盤上  
       if (saveGeneratedFiles) {  
           java.security.AccessController.doPrivileged(  
           new java.security.PrivilegedAction<Void>() {  
               public Void run() {  
                   try {  
                       FileOutputStream file =  
                           new FileOutputStream(dotToSlash(name) + ".class");  
                       file.write(classFile);  
                       file.close();  
                       return null;  
                   } catch (IOException e) {  
                       throw new InternalError(  
                           "I/O exception saving generated file: " + e);  
                   }  
               }  
           });  
       }  
  
    // 返回代理類的字節碼  
       return classFile;  
   }  

七、可以查看生成的代理實現類

     System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");  

public class Client1 {
	public static void main(String[] args) {
		System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");  
		LogHandler logHandler = new LogHandler();
		Subject subject = (Subject) logHandler.newProxyInstance(new RealSubject());
		subject.request();
	}
}

八、jd-gui查看生成的代理類

import com.yuanjun.proxy.demo.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0
  extends Proxy
  implements Subject
{
  private static Method m1;
  private static Method m2;
  private static Method m3;
  private static Method m0;
  
  public $Proxy0(InvocationHandler paramInvocationHandler)
    throws 
  {
    super(paramInvocationHandler);
  }
  //實現接口的方法,傳入InvocationHandler,調用invoke方法,實現動態代理
  public final void request()
    throws 
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

九、調用LogHandler裏的invoke方法

public class LogHandler implements InvocationHandler {
	
	
	  // 目標對象  
    private Object targetObject;  
    //綁定關係,也就是關聯到哪個接口(與具體的實現類綁定)的哪些方法將被調用時,執行invoke方法。              
    public Object newProxyInstance(Object targetObject){  
        this.targetObject=targetObject;  
        //該方法用於爲指定類裝載器、一組接口及調用處理器生成動態代理類實例    
        //第一個參數指定產生代理對象的類加載器,需要將其指定爲和目標對象同一個類加載器  
        //第二個參數要實現和目標對象一樣的接口,所以只需要拿到目標對象的實現接口  
        //第三個參數表明這些被攔截的方法在被攔截時需要執行哪個InvocationHandler的invoke方法  
        //根據傳入的目標返回一個代理對象  
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
                targetObject.getClass().getInterfaces(),this);  
    }  
	/**
	 * @param proxy 被代理的對象
	 * @param method 要調用的方法
	 * @param args  方法調用所需要的參數
	 */
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
			if(args!=null){
		 	System.out.println("start-->>");
		        for(int i=0;i<args.length;i++){  
		            System.out.println(args[i]);  
		        } 
		 	}
	        Object ret=null;  
	        try{  
	            /*原對象方法調用前處理日誌信息*/  
	            System.out.println("satrt-->>");  
	              
	            //調用目標方法  
	            ret=method.invoke(targetObject, args);  
	            /*原對象方法調用後處理日誌信息*/  
	            System.out.println("success-->>");  
	        }catch(Exception e){  
	            e.printStackTrace();  
	            System.out.println("error-->>");  
	            throw e;  
	        }  
	        return ret;  
	}

}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章