動態代理說明:將你提供的接口改造成和你這個類有關的代理對象。
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文件: