Dynamic proxy principle (for sample code, see Java reflection mechanism analysis (3 ))
A) understand the process of the above dynamic proxy example
B) proxy interface implementation class source code analysis
Let's take a look at the source code of the proxy implementation class ($ proxy0) and the entire dynamic proxy process.
The code generated by $ proxy0 is as follows:
Import Java. lang. reflect. invocationhandler; <br/> Import Java. lang. reflect. method; <br/> Import Java. lang. reflect. proxy; <br/> Import Java. lang. reflect. undeclaredthrowableexception; </P> <p> Public final class $ proxy0 extends proxy implements manager {</P> <p> Private Static Method M1; <br/> Private Static Method M0; <br/> Private Static Method m3; <br/> Private Static Method m2; </P> <p> static {<br/> try {<br/> m1 = Class. forname ("Java. lang. object "). getmethod ("equals", <br/> new class [] {class. forname ("Java. lang. object ")}); <br/> m0 = Class. forname ("Java. lang. object "). getmethod ("hashcode", <br/> new class [0]); <br/> m3 = Class. forname ("com. ML. test. manager "). getmethod ("test", <br/> new class [0]); <br/> m2 = Class. forname ("Java. lang. object "). getmethod ("tostring", <br/> new class [0]); <br/>} catch (nosuchmethodexception) {<br/> throw new nosuchmethoderror (nosuchmethodexception. getmessage (); <br/>} catch (classnotfoundexception) {<br/> throw new noclassdeffounderror (classnotfoundexception. getmessage (); <br/>}</P> <p> Public $ proxy0 (invocationhandler) {<br/> super (invocationhandler ); <br/>}</P> <p> @ override <br/> Public final Boolean equals (Object OBJ) {<br/> try {<br/> return (Boolean) super. h. invoke (this, M1, new object [] {OBJ}) <br/>. booleanvalue (); <br/>} catch (throwable) {<br/> throw new undeclaredthrowableexception (throwable ); <br/>}</P> <p> @ override <br/> Public final int hashcode () {<br/> try {<br/> return (integer) super. h. invoke (this, M0, null )). intvalue (); <br/>}catch (throwable) {<br/> throw new undeclaredthrowableexception (throwable ); <br/>}</P> <p> Public final void test () {<br/> try {<br/> super. h. invoke (this, M3, null); <br/> return; <br/>} catch (error e) {<br/>} catch (throwable) {<br/> throw new undeclaredthrowableexception (throwable ); <br/>}</P> <p> @ override <br/> Public final string tostring () {<br/> try {<br/> return (string) super. h. invoke (this, M2, null); <br/>} catch (throwable) {<br/> throw new undeclaredthrowableexception (throwable ); <br/>}< br/>}
The proxy interface implementation class implements the service class interface (the usermanager interface in the example) and inherits the base class proxy class;
The next step is the constructor. In the constructor, pass businesshandler to the constructor. Then, $ proxy0 calls the constructor of the parent class proxy and assigns a value to H (the proxy constructor should be used here );
Then we can see that this class overrides the equals, hashcode, and tostring methods of the proxy class, and implements the business class interface (that is, the test method of usermanager ), the specific rewriting and implementation are both super. h. invoke (that is, proxy. h. invoke.
After analyzing the proxy interface implementation class, let's take a look at how the dynamic proxy is implemented as a whole:
First, the client initializes the businesshandler class, and calls the newproxyinstance (New usermanagerimpl () method of this class to initialize the proxy interface implementation class above;
Next, the proxy interface implementation class passes businesshandler through the constructor (that is, this in the Code) and assigns a value to H through the constructor of the proxy;
Then the client will be able to generate a proxy interface implementation class $ proxy0, And we will forcibly convert it into a business implementation interface (usermanager) type (why force conversion is required, which is very interesting here, if no forced conversion is performed, an error is reported. It is well explained here, because the current environment does not know that this proxy interface implementation class $ proxy0 inherits both the proxy and the Business implementation interface usermanager, however, it can be forcibly converted to usermanager, because there is usermanager in the current environment. This is why reflection is amazing. You can call any class dynamically at runtime and use the details of this class .);
Then, when we call the test method, we actually call the test method in $ proxy0. The implementation of this method is through proxy. h invoke method implementation (that is, calling businesshandler. invoke method );
Then the method's invoke method is called (the parameters are this, And ARGs ).
In this way, the corresponding method of usermanagerimpl is called and then returned to the client.
This completes the entire call relationship.
I used the previous article to deeply analyze the dynamic proxy. Now I think it is very interesting. In fact, the most fundamental mechanism is the reflection mechanism, which dynamically instantiates any class during runtime, and the details of calling it. Looking back at the dynamic proxy example, we found that the most important thing here is the proxy. newproxyinstance (..) when the method is executed, the memory bytecode of $ proxy0 is generated. When we have the memory bytecode, our reflection will be very powerful, this gives us a series of calling relationships.
Through reflection mechanism analysis and Analysis of Dynamic proxy examples, we found that programming is so interesting that we are immersed in it.
Summary: Reflection, reflection, and the joy of programmers!