Dynamic proxy and its realization mechanism

Recommended for you: Get network issues from WhatsUp Gold. Not end users.

  A, use dynamic proxy

  Dynamic agents can provide to another object access, while hiding the actual object specific facts. The agent will generally achieve the actual object it represents the interface. The agent can access the object, but the delay to achieve some of the features of the actual object, the actual function of the actual object system, the proxy object hides the actual object to the customer. Customers don't know what it is and agency dealing with the actual object or deal with.

  Dynamic agent mainly comprises the following roles:

  Dynamic proxy classes (hereinafter referred to as the proxy class) is a realization of the list interface to create class specified in the run-time class, the class has the following description behavior.

  The interface is an interface agent class implementation.

  Proxy instance is an instance of the proxy class.

  Each agent instance has an associated call handler object, it can implement the interface InvocationHandler. By the method of proxy instance a proxy interface on the call is assigned to the Invoke method invocation handler instance, and transfer agent instance, array identification method call java.lang.reflect.Method object and contains the parameters of type Object. Method invocation call handler code in a proper way, and it returns a result will be returned as the result of the method invocation proxy instance.

  

  At present, the Java development kit contains the dynamic proxy support, but in fact we only support the implementation of the interface . In fact, we mainly through the java.lang.reflect.Proxy class and the java.lang.reflect.InvocationHandler interface.   Proxy class is mainly used to obtain the dynamic proxy object, the InvocationHandler interface is used to constrain the caller implementation

  Below an example:

  1 proxy interface: IComputer.java

1 package com.proxy;
2 
3 public interface IComputer {
4     void execute();
5 }

  2 is a proxy object: Laptop.java

 1 package com.proxy;
 2 
 3 //Notebook computer
 4 public class Laptop implements IComputer {
 5 
 6     public void execute() {
 7         System.out.println("Computer is in execution......");
 8     }
 9 
10 }

  The 3 call handling class: TimeHander.java

 1 package com.proxy;
 2 
 3 import java.lang.reflect.InvocationHandler;
 4 import java.lang.reflect.Method;
 5 
 6 public class TimeHander implements InvocationHandler {
 7     private Object object;
 8     public TimeHander(Object object) {
 9         this.object = object;
10     }
11     public Object invoke(Object proxy, Method method, Object[] args)
12             throws Throwable {
13         long start = System.currentTimeMillis();
14         System.out.println("start:"+start);
15         method.invoke(object, args);
16         Thread.sleep((int)(Math.random()*2000));
17         long end = System.currentTimeMillis();
18         System.out.println("end:"+end);
19         System.out.println("total:"+(end-start));
20         return null;
21     }
22 
23 }

  4 test procedure:

 1 package com.proxy;
 2 
 3 import java.lang.reflect.Proxy;
 4 
 5 public class ProxyTest {
 6 
 7     public static void main(String[] args) {
 8         Laptop laptop = new Laptop();
 9         TimeHander hander = new TimeHander(laptop);
10         IComputer computer = (IComputer)Proxy.newProxyInstance(laptop.getClass().getClassLoader(), laptop.getClass().getInterfaces(), hander);
11         computer.execute();
12     }
13 
14 }


The result of running the program:

start:1369118281186
Computer is in execution......
end:1369118282849
total:1663


  Two, the operation mechanism of dynamic proxy

  Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) Method returns an instance of the object class. As in the example above, IComputer computer = (IComputer) Proxy.newProxyInstance (laptop.getClass) (.GetClassLoader) (laptop.getClass), (.GetInterfaces), (hander); when carrying out the sentence will be generated by the reflection mechanism dynamics of a proxy class, This class implements the IComputer interface, And override method interface inside (i.e. the proxy class and to be the proxy class have the same interface), There is a InvocationHandler member variable in the proxy class., It is the call processing program, By calling the handler to be the proxy class enhancements. Create a proxy class and then call the class loader will be the class loading to save, and then through the reflection to create a an instance of the proxy class object.

  In order to be able to run mechanism of dynamic agents understand more, I own to achieve a dynamic proxy:

  1 proxy interface: Moveable.java

1 package com.test;
2 
3 public interface Moveable {
4     void move();
5 }

  2 is a proxy object: Tank.java

 1 package com.test;
 2 
 3 import java.util.Random;
 4 
 5 public class Tank implements Moveable {
 6 
 7     public void move() {
 8         System.out.println("Tank moving...");
 9         try {
10             Thread.sleep(new Random().nextInt(10000));
11         } catch (InterruptedException e) {
12             e.printStackTrace();
13         }
14     }
15 
16 }

  3 the following write a Proxy class to generate a proxy class object is the principal object, to increase the running time of the function of recording.

 1 package com.test;
 2 
 3 import java.io.File;
 4 import java.io.FileWriter;
 5 import java.lang.reflect.Constructor;
 6 import java.lang.reflect.Method;
 7 
 8 import javax.tools.JavaCompiler;
 9 import javax.tools.StandardJavaFileManager;
10 import javax.tools.ToolProvider;
11 import javax.tools.JavaCompiler.CompilationTask;
12 
13 public class Proxy {
14     public static Object newProxyInstance(Class interfaces,InvocationHandler h)throws Exception{
15         StringBuffer methodStr = new StringBuffer();
16         String tr = "\r\n";
17         Method[] methods = interfaces.getMethods();
18         //Splicing method of the proxy class
19         for (Method method : methods) {
20             methodStr.append(
21             "    public "+ method.getReturnType()+ " " +method.getName()+"() {" + tr +
22             "        try {" + tr +
23             "            java.lang.reflect.Method md = " + interfaces.getName() + "." + "class.getMethod(\""  + method.getName() + "\");" + tr +
24             "            h.invoke(this,md);" + tr +
25             "        }catch(Exception e) {e.printStackTrace();}" + tr +
26             "    }" + tr 
27             );
28         }
29         
30         //Stitching the proxy class
31         String src = "package com.test;" + tr +
32         "import com.test.Moveable;" + tr +
33         "public class TimeProxy implements " + interfaces.getName() + " {" + tr +
34         "    private com.test.InvocationHandler h;" + tr +
35         "    public TimeProxy(com.test.InvocationHandler h) {" + tr +
36         "        this.h = h;" + tr +
37         "    }" + tr +
38         methodStr.toString() + tr +
39         "}";
40         //Create the proxy class
41         String fileName = System.getProperty("user.dir") + "/src/com/test/TimeProxy.java";
42         File file = new File(fileName);
43         FileWriter writer = new FileWriter(file);
44         writer.write(src);
45         writer.flush();
46         writer.close();
47         //Compile
48         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
49         StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null);
50         Iterable units = fileMgr.getJavaFileObjects(fileName);
51         CompilationTask ct = compiler.getTask(null, fileMgr, null, null, null, units);
52         ct.call();
53         fileMgr.close();
54         //The class loading into memory: 
55         Class c = ClassLoader.getSystemClassLoader().loadClass("com.test.TimeProxy");
56         Constructor constructor = c.getConstructor(InvocationHandler.class); //The parameters obtained for constructing method of InvocationHandler type
57         Object m = constructor.newInstance(h); //Get through the method of constructing examples
58         return m;
59         
60     }
61 }

  4.TankProxy.java

 1 package com.test;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 public class TankProxy {
 6     public static <T> T getBean(final Object tank) throws Exception{
 7         return (T)Proxy.newProxyInstance(tank.getClass().getInterfaces()[0], new InvocationHandler(){
 8             public void invoke(Object proxy, Method method) {
 9                 long start = System.currentTimeMillis();
10                 System.out.println("start:"+start);
11                 try {
12                     method.invoke(tank, new Object[]{});
13                 } catch (Exception e) {
14                     e.printStackTrace();
15                 }
16                 long end = System.currentTimeMillis();
17                 System.out.println("end:"+end);
18                 System.out.println("time:"+(end-start));
19             }
20             
21         });
22     }
23 }    

  5 test procedure:

 1 package com.test;
 2 
 3 import java.util.List;
 4 
 5 import com.extend.Tank2;
 6 import com.extend.Tank3;
 7 import com.juhe.LogProxy;
 8 import com.juhe.TimeProxy;
 9 
10 public class Test {
11     public static void main(String[] args) throws Exception {
12         Tank tank = new Tank();
13         Moveable m =  TankProxy.getBean(tank);
14         m.move();
15         
16     }
17 
18 }

The result of executing the program for:
start:1369121253400
Tank moving...
end:1369121260078
time:6678

Dynamic proxy class generated content as follows:

 1 package com.test;
 2 import com.test.Moveable;
 3 public class TimeProxy implements com.test.Moveable {
 4     private com.test.InvocationHandler h;
 5     public TimeProxy(com.test.InvocationHandler h) {
 6         this.h = h;
 7     }
 8     public void move() {
 9         try {
10             java.lang.reflect.Method md = com.test.Moveable.class.getMethod("move");
11             h.invoke(this,md);
12         }catch(Exception e) {e.printStackTrace();}
13     }
14 
15 }

  

  Look at this example, the implementation mechanism of dynamic agents should have a certain understanding.!

   Summary: dynamic proxy at run time through a proxy class interface dynamically generated, which bring some flexibility for its flexibility, but it has two problems, first proxy class must implement an interface, if not implement the interface will throw an exception. Second performance impact, because the implementation mechanism of dynamic agents using reflection, the reflection is certainly better than direct calls to slow, then use reflection to generate a large number of class files may cause Full GC causing performance impact, because the area method bytecode file loading will be stored in the JVM run time zone (or permanent generation), when the method district full, will cause the Full GC, so when you use a lot of dynamic agent, can be permanent generation set some big, reduce the number of Full GC.  


Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download

Posted by Edmund at November 16, 2013 - 8:18 AM