package com.bjsxt.proxy;import java.lang.reflect.Method;public interface InvocationHandler { public void invoke(Object o, Method m);}Proxy.javapackage com.bjsxt.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 javax.tools.JavaCompiler;import javax.tools.StandardJavaFileManager;import javax.tools.ToolProvider;import javax.tools.JavaCompiler.CompilationTask;public class Proxy { public static Object newProxyInstance(Class infce, InvocationHandler h) throws Exception { //JDK6 Complier API, CGLib, ASM String methodStr = ""; String rt = "/r/n"; Method[] methods = infce.getMethods(); for(Method m : methods) { methodStr += "@Override" + rt + "public void " + m.getName() + "() {" + rt + " try {" + rt + " Method md = " + infce.getName() + ".class.getMethod(/"" + m.getName() + "/");" + rt + " h.invoke(this, md);" + rt + " }catch(Exception e) {e.printStackTrace();}" + rt + "}"; } String src = "package com.bjsxt.proxy;" + rt + "import java.lang.reflect.Method;" + rt + "public class $Proxy1 implements " + infce.getName() + "{" + rt + " public $Proxy1(InvocationHandler h) {" + rt + " this.h = h;" + rt + " }" + rt + " com.bjsxt.proxy.InvocationHandler h;" + rt + methodStr + "}"; String fileName = "d:/src/com/bjsxt/proxy/$Proxy1.java"; File f = new File(fileName); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close(); //compile JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(fileName); CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); //load into memory and create an instance URL[] urls = new URL[] {new URL("file:/" + "d:/src/")}; URLClassLoader ul = new URLClassLoader(urls); Class c = ul.loadClass("com.bjsxt.proxy.$Proxy1"); System.out.println(c); Constructor ctr = c.getConstructor(InvocationHandler.class); Object m = ctr.newInstance(h); //m.move(); return m; }}Proxy实现步骤:1.根据传过来的接口Class,遍历其中的方法(拼接使用InvocationHandler 调用方法的代码字符串),使用IO操作生成对应的java类文件2.根据步骤1生成的java类文件,使用JavaCompiler类将其编程成class3.使用URLClassLoader将class载入内存,调用class的构造方法实例化对象使用:Client.javapublic class Client { public static void main(String[] args) throws Exception { Tank t = new Tank(); InvocationHandler h = new TimeHandler(t); Moveable m = (Moveable)Proxy.newProxyInstance(Moveable.class, h); m.move(); }}CGLIB 和 JDK生成动态代理类
区别:JDK动态代理只能对实现了接口的类生成代理,而不能针对类 CGLIB是针对类实现代理,其原理是通过字节码技术为一个类创建子类,主要是对指定的类生成一个子类,覆盖其中的方法 ,因为是继承,所以该类或方法最好不要声明成final springAOP 使用的设计模式就是动态代理模式。如果目标对象实现了接口,则spring使用jdk 动态代理技术,如果目标对象没有实现接口,则spring使用CGLIB技术。
新闻热点
疑难解答