Java Dynamic proxy principle (proxy, invocationhandler), including $ proxy0 source code

Source: Internet
Author: User

 

Original article: http://www.2cto.com/kf/201109/103285.html

Today is okay. Let's review the previous knowledge and find it online. I found that one article is suitable.
Summary: JDK's dynamic proxy is actually a combination of reflection and dynamic bytecode generated during execution; for Spring AOP, JDK dynamic proxy is also used (cglib is also used ).
The following blogs are from the Internet:
 
I. Related Classes and methods:
Java. Lang. Reflect. Proxy,
Proxy provides static methods for creating dynamic proxy classes and instances.
Newproxyinstance ()
Returns the proxy instance of a specified API. This API can assign a method call to a specified handler.
(For details, see the API documentation)

Java. Lang. Reflect. invocationhandler,
Invocationhandler is the interface implemented by the call handler of the proxy instance.
Invoke ()
Process method calls on the proxy instance and return results. When a method is called on the proxy instance associated with the method, the method is called on the call handler.
(For details, see the API documentation)
Ii. Source Code:
Interface and implementation class of the proxy object:
 
Package com. ml. test;
 
Public interface manager {
Public void modify ();
}
 
Package com. ml. test;
 
Public class managerimpl implements manager {
 
@ Override
Public void modify (){
System. Out. println ("******* modify () method called ");
}
}
Service Proxy:
Package com. ml. test;
 
Import java. Lang. Reflect. invocationhandler;
Import java. Lang. Reflect. method;
 
Public class businesshandler implements invocationhandler {
 
Private object = NULL;
 
Public businesshandler (Object object ){
This. Object = object;
}
 
@ Override
Public object invoke (Object proxy, method, object [] ARGs)
Throws throwable {
System. Out. println ("do something before method ");
Object ret = method. Invoke (this. Object, argS );
System. Out. println ("do something after method ");
Return ret;
 
}
}

Client class:
 
Package com. ml. test;
Import java. Lang. Reflect. proxy;
Public class client {
 
Public static void main (string [] ARGs ){
// Meta object (proxy object)
Managerimpl = new managerimpl ();
 
// Service Proxy
Businesshandler securityhandler = new businesshandler (managerimpl );
 
// Obtain the instance of the proxy class ($ proxy0 extends proxy implements manager.
Manager managerproxy = (manager) proxy. newproxyinstance (managerimpl
. Getclass (). getclassloader (), managerimpl. getclass ()
. Getinterfaces (), securityhandler );
 
Managerproxy. Modify ();
}
}
Iii. Execution result:
Do something before Method
* ****** The modify () method is called.
Do something after Method
Iv. Mechanism Analysis:
Proxy. (classloader loader, class <?> [] Interfaces, invocationhandler h) Does the following.
(1) create a proxy class $ proxy Based on the getproxyclass (loader, interfaces) Call methods of loader and interfaces.
$ Proxy0 class implements the interfaces interface and inherits the proxy class.
(2) instantiate $ proxy0 and pass businesshandler In the constructor. Then $ proxy0 calls the constructor of the parent class proxy and assigns a value to H, as shown below:
Class proxy {
Invocationhandler H = NULL;
Protected proxy (invocationhandler h ){
This. H = h;
}
...
}

 

The following is the source code of the $ proxy0 class in this example (it is hard to put it forward ):
 
Import java. Lang. Reflect. invocationhandler;
Import java. Lang. Reflect. method;
Import java. Lang. Reflect. proxy;
Import java. Lang. Reflect. undeclaredthrowableexception;
 
Public final class $ proxy0 extends proxy implements manager {
 
Private Static Method M1;
Private Static Method M0;
Private Static Method m3;
Private Static Method m2;
 
Static {
Try {
M1 = Class. forname ("Java. Lang. Object"). getmethod ("equals ",
New Class [] {class. forname ("Java. Lang. Object ")});
M0 = Class. forname ("Java. Lang. Object"). getmethod ("hashcode ",
New Class [0]);
M3 = Class. forname ("com. ml. Test. Manager"). getmethod ("modify ",
New Class [0]);
M2 = Class. forname ("Java. Lang. Object"). getmethod ("tostring ",
New Class [0]);
} Catch (nosuchmethodexception ){
Throw new nosuchmethoderror (nosuchmethodexception. getmessage ());
} Catch (classnotfoundexception ){
Throw new noclassdeffounderror (classnotfoundexception. getmessage ());
}
}
 
Public $ proxy0 (invocationhandler ){
Super (invocationhandler );
}
 
@ Override
Public final Boolean equals (Object OBJ ){
Try {
Return (Boolean) Super. H. Invoke (this, M1, new object [] {OBJ }))
. Booleanvalue ();
} Catch (throwable ){
Throw new undeclaredthrowableexception (throwable );
}
}
 
@ Override
Public final int hashcode (){
Try {
Return (integer) Super. H. Invoke (this, M0, null). intvalue ();
} Catch (throwable ){
Throw new undeclaredthrowableexception (throwable );
}
}
 
Public final void modify (){
Try {
Super. H. Invoke (this, M3, null );
Return;
} Catch (error e ){
} Catch (throwable ){
Throw new undeclaredthrowableexception (throwable );
}
}
 
@ Override
Public final string tostring (){
Try {
Return (string) Super. H. Invoke (this, M2, null );
} Catch (throwable ){
Throw new undeclaredthrowableexception (throwable );
}
}
}
Then, convert the obtained $ proxy0 instance to manager.
When the managerproxy. Modify () method is executed, the modify () method in the $ proxy0 class is called.
In the modify method, call the invoke () method of H in the parent class proxy.
That is, invocationhandler. Invoke ();
The above section is the original statement of the original author. I will describe it in detail here:

Manager managerproxy = (manager) proxy. newproxyinstance (managerimpl
. Getclass (). getclassloader (), managerimpl. getclass ()
. Getinterfaces (), securityhandler );
 
In this statement, the $ proxy0 memory bytecode file is generated when the proxy. newproxyinstance (...) method is executed, and the return code is assigned
Managerproxy is forcibly converted to the Manager interface, and $ proxy0 also implements all the methods in the Manager interface.
Managerproxy. Modify (); the Code segment in $ proxy0 is called:

Public final void modify (){
Try {
Super. H. Invoke (this, M3, null); // in this section, invocationhandler. Invoke (); Super. H is both invocationhandler
Return;
} Catch (error e ){
} Catch (throwable ){
Throw new undeclaredthrowableexception (throwable );
}
}
In this way, the dynamic proxy mechanism is implemented.
Therefore, the key to Java Dynamic proxy is that the $ proxy0 memory bytecode and JDK reflection mechanism are generated when the proxy. newproxyinstance (...) method is executed!

Author: "Lin Qingyang-Technical blog"

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.