《Java知识应用》模式实现Java 动态代理
动态代理说明:将你提供的接口改造成和你这个类有关的代理对象。
Java动态代理案例和原理:https://www.cnblogs.com/jssj/p/11771408.html
我们无法像JVM一样不需要生成Java文件直接生成字节码。我们模拟就通过手工生成java,然后编译成Class文件来实现。
模式案例:
package demo.knowledgepoints.invocationhandler; public interface MyInvocationHandler { public Object invoke(); }
package demo.knowledgepoints.invocationhandler; public class MyInvocationHandlerImpl implements MyInvocationHandler { @Override public Object invoke() { System.out.println("===== MyInvocationHandlerImpl ====="); return null; } }
package demo.knowledgepoints.invocationhandler; public interface MyService { public void query(); }
package demo.knowledgepoints.invocationhandler; public class BinServvice implements MyService { @Override public void query() { System.out.println("===== start BinServvice ======="); } }
package demo.knowledgepoints.invocationhandler; public class TaoService implements MyService { @Override public void query() { System.out.println("========= start TaoService ========"); } }
package demo.knowledgepoints.invocationhandler; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; public class MyProxy { public static void main(String[] args) { try { MyInvocationHandler myInvocationHandler = new MyInvocationHandlerImpl(); MyService myService = (MyService) MyProxy.getInstance(new BinServvice(),myInvocationHandler); myService.query(); System.out.println("================================================"); myService = (MyService) MyProxy.getInstance(new TaoService(),myInvocationHandler); myService.query(); } catch (Exception e) { // } } public static Object getInstance(Object target, MyInvocationHandler myInvocationHandler) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { Class clazz = target.getClass().getInterfaces()[0]; Class myInvocationHandlerClazz = myInvocationHandler.getClass().getInterfaces()[0]; String interfaceName = clazz.getSimpleName(); //获取接口名称。 String content = ""; String line = "\n";//换行 String tab = "\t";//tab /****组装一个类start ***/ String packageContent = "package demo.knowledgepoints.invocationhandler;" + line; String importContent = "import " + clazz.getName() + ";" + line +"import " + myInvocationHandlerClazz.getName() + ";" + line; String clazzFirstLineContent = "public class $ProxyMy implements " + interfaceName + "{" + line; String myInvocationHandlerName= myInvocationHandlerClazz.getSimpleName(); String filedContent = tab + "private " + interfaceName + " target;" + line + tab + "private " + myInvocationHandlerName + " myInvocationHandler;" + line; String constructorContent = tab + "public $ProxyMy (" + interfaceName + " target,"+myInvocationHandlerName+" myInvocationHandler){" + line + tab + tab + "this.target =target;" + line + tab + tab + "this.myInvocationHandler = myInvocationHandler;" + line + tab + "}" + line; String methodContent = ""; /**获取传入接口中的全部方法***/ Method[] methods = clazz.getDeclaredMethods(); /**循环组装接口中的各个方法**/ for (Method method : methods) { //返回值类型 String returnTypeName = method.getReturnType().getSimpleName(); //方法名称 String methodName = method.getName(); // 参数类型的数组(int,String等) Class args[] = method.getParameterTypes(); String argsContent = ""; String paramsContent = ""; int flag = 0; for (Class arg : args) { //String String temp = arg.getSimpleName(); //String //String p0 argsContent += temp + " p" + flag + ","; //p0 paramsContent += "p" + flag + ","; flag++; } if (argsContent.length() > 0) { argsContent = argsContent.substring(0, argsContent.lastIndexOf(",") - 1); paramsContent = paramsContent.substring(0, paramsContent.lastIndexOf(",") - 1); } methodContent += tab + "public " + returnTypeName + " " + methodName + "(" + argsContent + ") {" + line + tab + tab + "myInvocationHandler.invoke();" + line + tab + tab + "target." + methodName + "(" + paramsContent + ");" + line + tab + "}" + line; } content += packageContent + importContent + clazzFirstLineContent + filedContent + constructorContent + methodContent + "}"; /****组装一个类end ***/ /****将上述组装的类写入文件中***/ File file = new File("d:\\Study\\AcceleateWorld\\study\\MyProcedure\\src\\demo\\knowledgepoints\\invocationhandler\\$ProxyMy.java"); try { if (!file.exists()) { file.createNewFile(); } FileWriter fw = new FileWriter(file); fw.write(content); fw.flush(); fw.close(); } catch (Exception e) { } /***使用JavaCompiler对象需要安装JDK,只有JAR无法使用**/ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(file); JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); /***将对象new出来读取到内存中***/ URL[] urls = new URL[]{new URL("file:d:\\Study\\AcceleateWorld\\study\\MyProcedure\\src\\\\")}; URLClassLoader urlClassLoader = new URLClassLoader(urls); Class cls = urlClassLoader.loadClass("demo.knowledgepoints.invocationhandler.$ProxyMy"); Class[] classes = new Class[]{clazz,myInvocationHandlerClazz}; Constructor constructor = cls.getConstructor(classes); Object o = constructor.newInstance(target,myInvocationHandler); return o; } }
运行效果:
生成的代理java文件和Class文件:
This moment will nap, you will have a dream; But this moment study,you will interpret a dream.