Design Pattern-dynamic proxy pattern, design pattern dynamic proxy
Dynamic proxies are used in many underlying frameworks, such as struts and Spring. Dynamic proxy is mainly used to enhance the method, so that you can enhance some methods without modifying the source code, and do anything you want to do before and after the method is executed, becauseInvocationHandlerIn the invoke method, you can directly obtainMethodFor specific applications, such as adding call logs and implementing transaction control. The so-called dynamic proxy refers to the dynamically generated proxy, which can solve many problems of this proxy class without writing, which greatly reduces our work. Now we simulate the implementation of jdk dynamic Proxy: 1. Method interface InvocationHandler. java
package com.bjsxt.proxy;import java.lang.reflect.Method;public interface InvocationHandler { public void invoke(Object o, Method m);}
2. Handling Method implementation (recording method running time) TimeHandler. java
package com.bjsxt.proxy;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;public class TimeHandler implements InvocationHandler{ private Object target; public TimeHandler(Object target) { super(); this.target = target; } @Override public void invoke(Object o, Method m) { long start = System.currentTimeMillis(); System.out.println("starttime:" + start); System.out.println(o.getClass().getName()); try { m.invoke(target); } catch (Exception e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println("time:" + (end-start)); }}
3. Proxy generation class Proxy. java
package 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(); //use jdk compiler to 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); return m; }}
4. Moveable. java
package com.bjsxt.proxy;public interface Moveable { void move(); }
5. Tank. java
package com.bjsxt.proxy;import java.util.Random;public class Tank implements Moveable { @Override public void move() { System.out.println("Tank Moving..."); try { Thread.sleep(new Random().nextInt(10000)); } catch (InterruptedException e) { e.printStackTrace(); } } }
6. client code
Package com. bjsxt. proxy; public 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 () ;}/// you can implement any proxy for any object or interface method.
In the Proxy. newProxyInstance (Moveable. class, h) method, the interface and processing method class are passed in. If there is an interface class, the interface method can be obtained and called;
The InvocationHandler class can be used to specify the processing method for the proxy object.
Generated proxy code $ Proxy1.java
package com.bjsxt.proxy;import java.lang.reflect.Method;public class $Proxy1 implements com.bjsxt.proxy.Moveable{ public $Proxy1(InvocationHandler h) { this.h = h; } com.bjsxt.proxy.InvocationHandler h;@Overridepublic void move() { try { Method md = com.bjsxt.proxy.Moveable.class.getMethod("move"); h.invoke(this, md); }catch(Exception e) {e.printStackTrace();}}}
For more details, see Java-horse soldier dynamic proxy mode.