How the Invoke method in the Java Dynamic agent is called automatically

Source: Internet
Author: User
Tags getmessage throwable

Reprint: http://www.shangxueba.com/jingyan/1853835.html

One, the difference between dynamic agent and static agent. (1) The Code of the proxy class is fixed, not because the business is gradually large and large, (2) can implement AOP programming, which is not implemented by static agents, (3) decoupling, if used in the web business, can realize the separation of the data layer and the business layer. (4) The advantage of dynamic agent is to implement non-intrusive code extension. Static proxy The model itself has a big problem, if the number of class methods more and more time, the proxy class code is very large. So the introduction of dynamic agents to solve such problems

Second, dynamic agent

Java in the implementation of dynamic agents, the key is the two things: Proxy, Invocationhandler, the following from the Invocationhandler interface of the Invoke method to start, a brief explanation of how Java implementation of dynamic Proxy.

First, the full form of the Invoke method is as follows:

Java code

    1. public object invoke (object proxy, Method method, object[] args) throws Throwable
    2. {
    3. Method.invoke (obj, args);
    4. return null;
    5. }

First guess is that method is called, that is, the method that needs to be executed; args is the parameter of the method; proxy, what is this parameter? The implementation of the Invoke () method above is the standard form, and we can see that the proxy parameter is not used here. View the description of the proxy in the JDK document as follows:

Java code

    1. A method invocation on a proxy instance through one of its proxy interfaces would be dispatched to the Invoke method of the Instance ' s invocation handler, passing the proxy instance,a Java.lang.reflect.Method object identifying the Method that W As invoked, and an array of type Object containing the arguments.

From this you can know that the above guesses are correct, but also know that the proxy parameter is passed is the agent class instance.

For illustrative purposes, here is a simple example to implement a dynamic proxy.

Java code

    1. Abstract role (dynamic agent can only proxy interface)
    2. Public interface Subject {
    3. public void request ();
    4. }

Java code

    1. Real character: Implement the request () method of subject
    2. public class Realsubject implements subject{
    3. public void request () {
    4. System.out.println ("from real subject.");
    5. }
    6. }

Java code

    1. Realized the Invocationhandler
    2. public class Dynamicsubject implements Invocationhandler
    3. {
    4. Private Object obj;//This is the benefit of dynamic proxies, which are encapsulated objects of type object and accept arbitrary types of objects
    5. Public Dynamicsubject ()
    6. {
    7. }

Public dynamicsubject (Object obj)

11. {

This.obj = obj;

13.}

    1. 14.

15.//This method is not the one we show to call

public object invoke (object proxy, method, object[] args) throws Throwable

17. {

System.out.println ("before calling" + method);

    1. 19.

Method.invoke (obj, args);

    1. 21st.

System.out.println ("After calling" + method);

    1. 23.

. return null;

25.}

    1. 26.

27.}

Java code

    1. Client: Generates the proxy instance and invokes the request () method
    2. public class Client {
    3. public static void Main (string[] args) throws throwable{
    4. TODO auto-generated Method Stub
    5. Subject rs=new realsubject ();//Specify the proxy class here
    6. Invocationhandler ds=new Dynamicsubject (RS);
    7. Classcls=rs.getclass ();
    8. 10.

11.//The following is a one-time generation agent

    1. 12.

Subject subject= (Subject) proxy.newproxyinstance (

Cls.getclassloader (), Cls.getinterfaces (), DS);

    1. 15.

16.//This can be proved by running the result subject is an example of a proxy, this example implements the subject interface

System.out.println (subject instanceof Proxy);

    1. 18.

19.//Here you can see that subject class is $proxy0, this $proxy0 class inherits the proxy, realizes the subject interface

System.out.println ("Subject class is:" +subject.getclass (). toString ());

    1. 21st.

System.out.print ("The attributes in subject are:");

    1. 23.

Field[] Field=subject.getclass (). Getdeclaredfields ();

(Field F:field) {

System.out.print (F.getname () + ",");

27.}

    1. 28.

The methods in System.out.print ("\ n" + "Subject are:");

    1. 30.

Method[] Method=subject.getclass (). Getdeclaredmethods ();

    1. 32.

(Method M:method) {

System.out.print (M.getname () + ",");

35.}

    1. 36.

The parent class of System.out.println ("\ n" + "subject" is: "+subject.getclass (). Getsuperclass ());

    1. 38.

System.out.print ("\ n" + "subject implements the interface is:");

    1. 40.

Class[] Interfaces=subject.getclass (). Getinterfaces ();

    1. 42.

. for (classi:interfaces) {

System.out.print (I.getname () + ",");

45.}

    1. 46.

System.out.println ("\ n" + "operation result is:");

Subject.request ();

49.}

50.}

XML code

    1. The result of the operation is as follows: The package name is omitted here, instead
    2. True
    3. Subject class is: Class $Proxy 0
    4. The attributes in subject are: M1, M3, M0, M2,
    5. The methods in subject are: request, hashcode, Equals, toString,
    6. Subject's parent class is: Class Java.lang.reflect.Proxy
    7. The interfaces implemented by Subject are: Cn.edu.ustc.dynamicproxy.Subject,
    8. The result of the operation is:

Ten. Before calling public abstract void * * *. Subject.request ()

One. from real subject.

After calling public abstract void * * *. Subject.request ()

PS: The information of this result is very important, at least for me. Because I am in the dynamic agent of the cause of the halo is that the above subject.request () is misunderstood, at least by the surface of the confusion, did not find the connection between the subject and proxy, once tangled in the last Call of this request () is how and invoke () Contact, and invoke is how to know that the request exists. In fact, the above true and class $Proxy 0 can solve a lot of doubts, coupled with the following will be said $proxy0 source code, can completely solve the dynamic agent doubts.

As you can see from the above code and results, we do not show the Invoke Invoke () method, but this method does. Here's an analysis of the whole process:

From the code in the client, we can take the method of Newproxyinstance as a breakthrough, first we look at the source code of the Newproxyinstance method in the proxy class:

Java code

    1. public static Object newproxyinstance (ClassLoader loader,
    2. Class[] interfaces,
    3. Invocationhandler h)
    4. Throws IllegalArgumentException
    5. {
    6. if (h = = null) {
    7. throw new NullPointerException ();
    8. }

10./*

* Look up or generate the designated proxy class.

12. */

Class cl = getproxyclass (loader, interfaces);

    1. 14.

15./*

* Invoke its constructor with the designated invocation handler.

17. */

try {

19./*

* Proxy source code begins to have such a definition:

* Private final static class[] Constructorparams = {Invocationhandler.class};

* Cons is the construction method of the form parameter to the Invocationhandler type

23. */

Constructor cons = Cl.getconstructor (constructorparams);

Return (Object) cons.newinstance (new object[] {h});

.} catch (Nosuchmethodexception e) {

Internalerror throw New (E.tostring ());

.} catch (Illegalaccessexception e) {

throw new Internalerror (e.tostring ());

.} catch (Instantiationexception e) {

throw new Internalerror (e.tostring ());

.} catch (InvocationTargetException e) {

throw new Internalerror (e.tostring ());

34.}

35.}

Proxy.newproxyinstance (ClassLoader loader, class[] interfaces, Invocationhandler h) has done the following several things.

(1) The proxy class interfaces is created according to the parameters loader and interfaces call method Getproxyclass (loader, $proxy0). $Proxy Class 0 implements the interfaces interface and inherits the proxy class.

(2) Instantiate the $proxy0 and pass the Dynamicsubject in the construction method, then $proxy0 call the constructor of the parent class proxy, assign the value to H, as follows:

Java code

    1. Class proxy{
    2. Invocationhandler H=null;
    3. Protected Proxy (Invocationhandler h) {
    4. This.h = h;
    5. }
    6. ...
    7. }

Take a look at the source code of the $proxy0 that inherits the proxy:

Java code

    1. Public final class $Proxy 0 extends Proxy implements Subject {
    2. private static Method M1;
    3. private static Method M0;
    4. private static Method m3;
    5. private static Method m2;
    6. static {
    7. try {
    8. M1 = Class.forName ("Java.lang.Object"). GetMethod ("equals",

New class[] {class.forname ("Java.lang.Object")});

    1. 11.

M0 = Class.forName ("Java.lang.Object"). GetMethod ("Hashcode",

New Class[0]);

    1. 14.

M3 = Class.forName ("* * *. Realsubject "). GetMethod (" Request ",

New Class[0]);

    1. 17.

M2 = Class.forName ("Java.lang.Object"). GetMethod ("ToString",

New Class[0]);

    1. 20.

.} catch (Nosuchmethodexception nosuchmethodexception) {

throw new Nosuchmethoderror (Nosuchmethodexception.getmessage ());

.} catch (ClassNotFoundException classnotfoundexception) {

throw new Noclassdeffounderror (Classnotfoundexception.getmessage ());

25.}

//static.}

    1. 27.

0 public $Proxy (Invocationhandler Invocationhandler) {

Super (Invocationhandler);

30.}

    1. 31.

@Override.

. Public final Boolean equals (Object obj) {

. try {

Return ((Boolean) Super.h.invoke (this, M1, new object[] {obj})). Booleanvalue ();

.} catch (Throwable throwable) {

Panax Notoginseng throw new Undeclaredthrowableexception (Throwable);

38.}

39.}

    1. 40.

@Override.

Public final int hashcode () {

. try {

The. return ((Integer) Super.h.invoke (this, M0, null)). Intvalue ();

Throwable} catch (Throwable) {

Undeclaredthrowableexception. throw new (Throwable);

47.}

48.}

    1. 49.

Public final void request () {

. try {

Super.h.invoke (this, M3, null);

. return;

A.} catch (Error e) {

.} catch (Throwable throwable) {

. throw new Undeclaredthrowableexception (Throwable);

57.}

58.}

    1. 59.

@Override.

A. Public final String toString () {

. try {

. return (String) Super.h.invoke (this, M2, null);

.} catch (Throwable throwable) {

N. throw new Undeclaredthrowableexception (Throwable);

66.}

67.}

68.}

The resulting $proxy0 instance is then cast to subject and the reference is assigned to subject. When the Subject.request () method is executed, the request () method in the $proxy0 class is called, and the Invoke () method of H in the parent class proxy is called. That is, Invocationhandler.invoke ().

Ps:1, it should be stated that the Getproxyclass method in the proxy class returns the class of the proxy. The reason for this is that I made a low-level mistake at first, and thought that I was returning the class class of the agent--! Recommended to see the source of getproxyclass, very long =. =

2, from the source of $proxy0 can be seen, the dynamic proxy class not only proxy display defined interface methods, but also proxy Java root class object inherited from the Equals (), Hashcode (), toString () The three methods, and only the three methods.

Q: So far, there is a doubt that the first parameter in the Invoke method is an instance of the proxy (and, to be exact, the end use of the $proxy0 instance), but what is the use? Or, how does the Cheng show the effect?

A: In my current level, this proxy parameter does not have any effect, in the entire dynamic agent mechanism, and does not use the Invocationhandler invoke method of the proxy parameter. The parameter passed in is actually an instance of the proxy class. I think it's possible for programmers to use reflection in the Invoke method to get some information about the proxy class.

How the Invoke method in the Java Dynamic agent is called automatically

Related Article

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.