[Design mode] dynamic proxy & Simulate JDK dynamic proxy

Source: Internet
Author: User

To understand the dynamic proxy, you need to answer the following questions:

What is dynamic proxy? How?

What is the role of dynamic proxy? Configurable transactions, permission control, logs, and so on .... You can't do it without dynamic proxies.


To answer the above three questions:

Let's startStatic proxy:

Method: Create a proxy class. The proxy class contains the method of the proxy object and adds the method before and after the proxy method.

You can create a proxy class by using an inherited interface or an aggregate interface of the proxy object, and then pass in the instance of the proxy object. Aggregation and inheritance are good. When using inheritance, if the proxy class needs to be nested or create different proxy classes, you need to create different proxy classes. Causes class flooding.

Aggregation means that the interface implementation method is better and more flexible, because if each proxy class inherits the interface of the proxy object, you only need to input different proxy instances in a proxy class to implement different proxies, so that they can be freely combined.


However, static proxies still have disadvantages. To implement proxy functions, you must manually write proxy classes and logic. To implement multiple proxy functions, you still need to write multiple proxy classes.

Therefore, we need to fix the proxy class proxy code, and then dynamically pass in the objects to be proxies and directly pass in the proxy logic. In this way, the proxy class can be fixed. This is the so-called dynamic meaning. Proxy provides a proxy for other objects to control access to this object, that is, to insert other functions into the target object, instead of modifying the code (or structure) inside the object ).

To sum up, we can implement arbitrary proxy (custom) for any objects, interface methods, and other proxies without having to change the code of the proxy object ).


To illustrate the advantages of dynamic proxy and the principle of JDK dynamic Proxy:

Let me simulate the implementation process of JDK dynamic Proxy:

Fixed proxy code and implemented dynamic results

We use Java complier to compile the character stream (to define characters for simplicity). class source code to the working directory (or custom directory), and then load the class object into the memory to generate a class. When creating a class, the constructor passes in the proxy logic, the class here is the interface to be proxy. Both are dynamically specified during client calls.

The following is the code dynamically generated by proxy:

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, asmstring methodstr = ""; string RT = "\ r \ n"; method [] Methods = INFCE. getmethods ();/* For (method M: Methods) {methodstr + = "@ override" + RT + "Public void" + M. getname () + "() {" + RT + "Long start = system. currenttimemillis (); "+ RT +" system. out. println (\ "starttime: \" + start); "+ RT +" T. "+ M. getname () + "();" + RT + "long end = system. currenttimemillis (); "+ RT +" system. out. println (\ "Time: \" + (end-Start); "+ RT +"} ";} */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 (); // compilejavacompiler compiler = toolprovider. getsystemjavacompiler (); standardjavafilemanager filemgr = compiler. getstandardfilemanager (null, null, null); iterable Units = filemgr. getjavafileobjects (filename); compilationtask T = compiler. gettask (null, filemgr, null, units); T. call (); filemgr. close (); // load into memory and create an instanceurl [] 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); // generate an object through the constructor // M. move (); Return M ;}}

The dynamic proxy code generated by calling the above dynamic compilation is as follows (generated under the specified directory ):

Here, moveable is the interface of the proxy object we specified (this object is the proxy target, not the instance object, this means that the incoming instance is not a proxy object but a common interface of the proxy object and proxy class, while invocationhandler is also an interface of the proxy logic, and invationhandler is also writable (this is also flexible, in this way, you can configure different agent logic in the configuration file (polymorphism) without changing.

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();}}}

Fixed invocationhandler interface (different from the original JDK version, but consistent with the principle ):

package com.bjsxt.proxy;import java.lang.reflect.Method;public interface InvocationHandler {public void invoke(Object o, Method m);}

The programmer's own implements invocationhandler interface internally specifies (object) to indicate the accepted proxy object (Interface) target, and then writes the proxy logic (add it by himself before and after the proxy object method ), the call method uses the dynamic call of invoke. The Code is as follows:

Package COM. bjsxt. proxy; import Java. lang. reflect. method; public class timehandler implements invocationhandler {private object target; Public timehandler (object target) implements super({%this.tar get = target ;}@ overridepublic void invoke (Object o, method m) {// your own proxy logic long start = system. currenttimemillis (); system. out. println ("starttime:" + start); system. out. println (O. getclass (). getname (); try {// call target. m method, which can process any class and any method (passed in) M. invoke (target);} catch (exception e) {e. printstacktrace ();} long end = system. currenttimemillis (); system. out. println ("time:" + (end-Start ));}}

Next, create your own proxy object in the client and create the proxy logic instance. Then, pass the proxy logic instance and the proxy object interface into the proxy class to generate the proxy class instance, and finally execute the proxy method, the target code is not modified (or unknown, for example. class) to add the function at the code aspect layer. The proxy classes can also be encapsulated, because they all inherit the proxy object interface.

The client call is attached below:

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.


The running result of the program is as follows: the time log is added before and after the moveable method.


If you have any misunderstandings or are not clear about your language, you are welcome to criticize and correct it.


[Design mode] dynamic proxy & Simulate JDK dynamic proxy

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.