关于动态代理原理

关于jdk的proxy看了几遍,每次记住了,过了一段时间,又容易忘记 java

今天仔细看了一下,发现实际上Proxy.newInstance就是动态生成了一个Proxy.class文件,而后我用jad反编译以后发现,就是生成了一个类,implement以前写的interface,而后全部的方法都写成final了 数组

反编译后代码以下 this

public final int say(String s, String s1)
    {
        try
        {
            return ((Integer)super.h.invoke(this, m3, new Object[] {
                s, s1
            })).intValue();
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }

    public final ArrayList list(String s, int i)
    {
        try
        {
            return (ArrayList)super.h.invoke(this, m4, new Object[] {
                s, Integer.valueOf(i)
            });
        }
        catch(Error _ex) { }
        catch(Throwable throwable)
        {
            throw new UndeclaredThrowableException(throwable);
        }
    }



原理是,proxy经过newProxyInstance传递参数,加载器,全部interface,还有invocatoinhandler实现类,根据getProxyClass 获取被代理类,而后反射读取被代理的构造方法,实现全部接口

如今代理类生成了,如何调用hander里面的invoke呢 代理

步骤1.Class cl = getProxyClass(loader, interfaces); 获取代理类的class code

步骤2.Constructor cons = cl.getConstructor(constructorParams); 获取proxy的子类的构造方法 对象

        constructorParams 的值为 new class[]{invocationhandler.class}; 继承

步骤3.获取实体类对象 接口

         return (Object) cons.newInstance(new Object[] { h }); get


由于生成的代理类继承Proxy,实现了咱们传进去的接口,全部接口执行方法,直接调用生成的Proxy里面的final方法,返回结果就是,调用传进去的handler的invoke方法,参数this, it

return (ArrayList)super.h.invoke(this, m4, new Object[] {
                s, Integer.valueOf(i)
            }); 第一个参数就是当前Proxy,第二个是方法Method,第三个是args

还有Object... args这种参数实际上编译之后是object[] 数组,是java的语法糖

而后就执行咱们的handler里面定义的invoke方法了

public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("aaa:"+proxy.getClass().getName());
		 Object temp =method.invoke(this.o, args);
		 return temp;
	}



返回的结果就是方法执行的结果,void也是一种object


如下附java生成字节码方法:

public class ProxyGeneratorUtils {
    /** 
     * 把代理类的字节码写到硬盘上 
     * @param path 保存路径 
     */  
    public static void writeProxyClassToHardDisk(String path) {  
        // 第一种方法,这种方式在刚才分析ProxyGenerator时已经知道了  
        // System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);  
          
        // 第二种方法  
          
        // 获取代理类的字节码  
        byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy11", SujectImpl.class.getInterfaces());  
          
        FileOutputStream out = null;  
          
        try {  
            out = new FileOutputStream(path);  
            out.write(classFile);  
            out.flush();  
        } catch (Exception e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                out.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
    public static void main(String[] args) {
    	ProxyGeneratorUtils.writeProxyClassToHardDisk("F:/$Proxy11.class");  
	}
}
你们能够试一下
相关文章
相关标签/搜索