JDK动态代理实现原理(简析加转载)

这里探讨JDK动态代理是如何实现的。JDK生成动态代理的语法如下,参考JDK动态代理示例

Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),
new Class[]{Interface.class},
new DynamicProxyHandler(real));

关键是看newProxyInstance方法是如何工作的,再探讨这个方法之前,先分析一篇看到的日志。这个日志大体实现了一个自定义的Proxy类,称为MyProxy类。代码会在后面给出。这里分析几个要点:

1、关键是生成代理类的字节码文件(生成后放在磁盘上),然后通过类加载器加载这个字节码文件。
这个代理类要implements参数中传入的所有接口,并实现其中的方法。

2、关于如何实现接口中的方法,其实只要拼一个相应方法的方法体,然后调用参数中DynamicProxyHandler的invoke方法,使用反射机制。

MyProxy的代码如下,不确定准不准确,会继续研究:

package com.itzhai.javanote.proxy;

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;

import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

public class MyProxy {  

    public static Object newProxyInstance(Class interfaces,MyInvocationHandler handler) throws Exception{  
        String r = "\n";

        Method[] methods = interfaces.getMethods();  

        StringBuffer sb = new StringBuffer("");  
        //生成需要代理的接口中的所有方法 的代码,通过调用MyInvocationHandler的invoke方法实现真实对象方法的调用
        for(int i =0;i<methods.length;i++){
            sb.append(" public void "+methods[i].getName()+"() {"+ r +  
            "       try{ "+ r +  
            "       Method md = "+interfaces.getName()+".class.getMethod(\""+methods[i].getName()+"\");"+ r +  
            "       handler.invoke( md,new Object[]{});"+ r +  
            "       }catch(Exception e){e.printStackTrace();}"+ r +     
            "   }"+r + r
            );  
        }

        // 生成完整的类代码
        String src = "package com.itzhai.javanote.proxy;"+ r + r + 
                     "import java.lang.reflect.*;"+ r + r + 
        "public class Proxy$1 implements "+interfaces.getName() +"{"+ r +  

        "   private com.itzhai.javanote.proxy.MyInvocationHandler handler;"+ r +  

        "   public Proxy$1("+handler.getClass().getName() +" handler){"+ r +  
        "       this.handler = handler;"+ r +  
        "   }"+ r + r +  

            sb.toString() +  

        "}" +r;  
        // 输出Java文件
        String dir = System.getProperty("user.dir")+"/src/com/itzhai/javanote/proxy/";  
        FileWriter writer = new FileWriter(new File(dir+"Proxy$1.java"));  
        writer.write(src);  
        writer.flush();  
        writer.close();  
        // 编译动态代理类
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);  
        Iterable<? extends JavaFileObject> units = fileMgr.getJavaFileObjects(dir+"Proxy$1.java");
        Iterable<String> options = Arrays.asList("-d", System.getProperty("user.dir") + "/bin/");
        CompilationTask t = compiler.getTask(null, fileMgr, null, options, null, units);  
        t.call();  
        fileMgr.close();  

        // 加载动态代理类,并返回动态代理类的实例
        URL[] urls = new URL[]{new URL("file:/"+dir)};  
        URLClassLoader loader = new URLClassLoader(urls);  
        Class c = loader.loadClass("com.itzhai.javanote.proxy.Proxy$1");  
        Constructor ctr = c.getConstructor(handler.getClass());  
        return ctr.newInstance(handler);  
    }  
}

参考:
http://www.itzhai.com/java-dong-tai-dai-li-zhi-jdk-dong-tai-dai-li-he-cglib-dong-tai-dai-li-mian-xiang-qie-mian-bian-cheng-aop-yuan-li.html#read-more

http://rejoy.iteye.com/blog/1627405

http://blog.csdn.net/zhangerqing/article/details/42504281

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值