[Reprint] Java dynamic agent mechanism of the detailed

Source: Internet
Author: User
Tags throwable what interface

Reprinted from Http://www.cnblogs.com/xiaoluo501395377/p/3383130.html

Proxy mode
Proxy mode is a common Java design pattern, his characteristic is that the proxy class and the delegate class have the same interface, the proxy class is mainly responsible for the delegate class preprocessing messages, filtering messages, forwarding messages to the delegate class, and post-processing messages. There is usually an association between the proxy class and the delegate class, and the object of a proxy class is associated with an object of a delegate class, and the object of the proxy class does not actually implement the service, but instead provides a specific service by invoking the related method of the object of the delegate class.
The proxy class can be divided into two types according to the agent's creation period.
Static proxy: The source code is generated automatically by the programmer or a specific tool, and then compiled. Before the program runs, the. class file for the proxy classes already exists.
Dynamic Agent: When the program is running, it is created dynamically using the reflection mechanism.

First look at the static proxy:
1, Count.java

  1. Package Net.battier.dao;
  2. /**
  3. * Define an Account interface
  4. *
  5. * @author Administrator
  6. *
  7. */
  8. Public interface Count {
  9. //View account method
  10. public void Querycount ();
  11. //Modify account method
  12. public void Updatecount ();
  13. }


2, Countimpl.java

  1. Package Net.battier.dao.impl;
  2. Import Net.battier.dao.Count;
  3. /**
  4. * Delegate Class (Contains business logic)
  5. *
  6. * @author Administrator
  7. *
  8. */
  9. Public class Countimpl implements Count {
  10. @Override
  11. public void Querycount () {
  12. System.out.println ("View account Method ...");
  13. }
  14. @Override
  15. public void Updatecount () {
  16. System.out.println ("Modify Account Method ...");
  17. }
  18. }
  19. , Countproxy.java
  20. Package Net.battier.dao.impl;
  21. Import Net.battier.dao.Count;
  22. /**
  23. * This is a proxy class (Enhanced Countimpl implementation Class)
  24. *
  25. * @author Administrator
  26. *
  27. */
  28. Public class Countproxy implements Count {
  29. private Countimpl Countimpl;
  30. /** 
  31. * Override the default constructor
  32. *
  33. * @param Countimpl
  34. */
  35. Public Countproxy (Countimpl countimpl) {
  36. This.countimpl = Countimpl;
  37. }
  38. @Override
  39. public void Querycount () {
  40. System.out.println ("before transaction processing");
  41. //method of invoking the delegate class;
  42. Countimpl.querycount ();
  43. System.out.println ("after transaction processing");
  44. }
  45. @Override
  46. public void Updatecount () {
  47. System.out.println ("before transaction processing");
  48. //method of invoking the delegate class;
  49. Countimpl.updatecount ();
  50. System.out.println ("after transaction processing");
  51. }
  52. }

3, Testcount.java

  1. Package net.battier.test;
  2. Import Net.battier.dao.impl.CountImpl;
  3. Import Net.battier.dao.impl.CountProxy;
  4. /**
  5. * Test Count class
  6. *
  7. * @author Administrator
  8. *
  9. */
  10. Public class Testcount {
  11. public static void Main (string[] args) {
  12. Countimpl Countimpl = new Countimpl ();
  13. Countproxy countproxy = new Countproxy (Countimpl);
  14. Countproxy.updatecount ();
  15. Countproxy.querycount ();
  16. }
  17. }

Observation code can find that each proxy class can only serve one interface, so that the development of the program will inevitably generate too many agents, and all the agent operation in addition to the method called, the other operations are the same, then it must be duplicated code. The best way to solve this problem is to complete the proxy function through a proxy class, which must be done using dynamic proxy.

When we learn spring, we know that spring has two main ideas, one is the IOC, the other is AOP, and for IOC, dependency injection doesn't have to be said, and for spring's core AOP, we not only need to know how to satisfy our function through AOP, What we need to learn is how the underlying is a principle, and the principle of AOP is the dynamic agent mechanism of Java, so this essay is a review of the dynamic mechanism of java.

In the dynamic agent mechanism of Java, there are two important classes or interfaces, one is Invocationhandler (Interface), the other is proxy (class), and this class and interface is necessary to implement our dynamic proxy. First, let's take a look at how the Java API Help document describes these two classes:

Invocationhandler:

Invocationhandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance have an associated invocation handler. When a method was invoked on a proxy instance, the method invocation was encoded and dispatched to the Invoke method of its Invocation handler.

Each dynamic proxy class must implement the Invocationhandler interface, and each instance of the proxy class is associated with a handler, and when we call a method through the proxy object, The invocation of this method is forwarded to the Invoke method of this interface by Invocationhandler. Let's take a look at the only way to invocationhandler this interface. The Invoke method:

Object Invoke (Object proxy, Method method, object[] args) throws Throwable

We see that this method takes three parameters altogether, so what do these three parameters represent?

Object Invoke (Object proxy, method, object[] args) throws Throwableproxy: refers to the real object we represent. method: refers to the method object that we are going to call the real object of a way. args: refers to the arguments that are accepted when a method of a real object is called

If not very clear, wait for an example to explain these parameters in more depth.

Next we look at the proxy class:

The role of the proxy class is to dynamically create a class of proxy objects, which provides a number of methods, but the most we use is newproxyinstance this method:

public static Object newproxyinstance (ClassLoader loader, class<?>[] interfaces,  Invocationhandler h)  Throws IllegalArgumentException
Returns an instance of a proxy class for the specified interfaces, dispatches method invocations to the specified INVO cation handler.

The function of this method is to get a dynamic proxy object, which receives three parameters, and we take a look at what these three parameters mean:

public static Object newproxyinstance (ClassLoader loader, class<?>[] interfaces, Invocationhandler h) throws IllegalArgumentExceptionLoader: A ClassLoader object that defines which ClassLoader object to load on the generated proxy object Interfaces: An array of interface objects, which means that I'm going to provide a set of interfaces to the object I need to proxy, and if I provide a set of interfaces to it, then this proxy object declares that the interface is implemented (polymorphic), So I can invoke the method in this set of interfaces H: A Invocationhandler object that represents the Invocationhandler object to which the dynamic proxy object will be associated when it calls the method. 

Well, after the introduction of these two interfaces (classes), let's look at an example of what our dynamic proxy pattern looks like:

First we define an interface of type subject and declare two methods for it:

Public interface subject{public    void rent ();        public void Hello (String str);

Next, define a class to implement this interface, this class is our real object, Realsubject class:

public class Realsubject implements subject{    @Override public    void rent ()    {        System.out.println ("I Want to rent my house ");        @Override public    void Hello (String str)    {        System.out.println ("Hello:" + str);}    }

Next, we are going to define a dynamic proxy class, the previous one, each dynamic proxy class must implement Invocationhandler this interface, so we this dynamic proxy class is no exception:

public class Dynamicproxy implements invocationhandler{    //This is what we want to proxy the real object of    private objects subject;    constructs the method, assigns the real object which we want the proxy to assign the initial value public    dynamicproxy (object subject)    {        this.subject = subject;    }        @Override Public    object Invoke (Object object, method method, object[] args)            throws Throwable    {        // We can add some of our own operation        System.out.println ("before Rent House") before acting on the real object.                System.out.println ("Method:" + method);    when a contemporary object invokes a method of a real object, it automatically jumps to the proxy object's associated handler object's Invoke method to invoke        Method.invoke (subject, args);                We can also add some of our own operation        System.out.println ("After the Rent house") when acting on the real object.                return null;}    }

Finally, take a look at our client class:

public class client{public    static void Main (string[] args)    {        //    The real object we want to proxy        Subject realsubject = New Realsubject ();    we want to proxy which real object, the object is passed in, and finally through the real object to invoke its method of        Invocationhandler handler = new Dynamicproxy (realsubject);        /*         * Using Proxy's Newproxyinstance method to create our proxy object, let's take a look at its three parameters         * The first parameter Handler.getclass (). getClassLoader (), Here we use the ClassLoader object of the handler class to load our proxy object         * The second parameter Realsubject.getclass (). Getinterfaces (), The interface that we provide for the proxy object is the interface that the real object implements, which means that I am going to proxy the real object so that I can invoke the method in this set of interfaces         * The third parameter handler, where we associate this proxy object to the top of the Invocationhandler on this object         */        Subject Subject = (Subject) proxy.newproxyinstance (Handler.getclass (). getClassLoader (), Realsubject                . GetClass (). Getinterfaces (), handler);                System.out.println (Subject.getclass (). GetName ());        Subject.rent ();        Subject.hello ("World");}    }

Let's take a look at the console output:

$Proxy 0
Before rent Housemethod: publicabstract void com.xiaoluo.dynamicproxy.Subject.rent ()I want to rent my Houseafter Rent House
Before rent Housemethod: publicabstract void Com.xiaoluo.dynamicproxy.Subject.hello (java.lang.String) Hello:worldafter Rent House

Let's start by looking at $Proxy 0 this thing we see, this thing is made by System.out.println (Subject.getclass (). GetName ()); This statement is printed, so why is the class name of the proxy object that we return?

Subject Subject = (Subject) proxy.newproxyinstance (Handler.getclass (). getClassLoader (), Realsubject                . GetClass () . Getinterfaces (), handler);

Maybe I thought the returned proxy object would be an object of type subject or a Invocationhandler object, but the result is not, first we explain why we can convert it to an object of type subject? the reason is that in newproxyinstance the second parameter of this method, we give this proxy object to provide a set of what interface, then I this proxy object will implement this set of interfaces, this time we can of course, this proxy object coercion type into any of the set of interfaces , because the interface here is the subject type, so it can be converted to the subject type.

at the same time we must remember that the proxy object created through Proxy.newproxyinstance is an object that is dynamically generated when the JVM is running, it is not our invocationhandler type, nor is it the type of the set of interfaces we define. Instead, the run is a dynamically generated object, and the naming method is in this form, starting with $, proxy is medium, and the last number represents the label of the object .

Then we'll take a look at these two sentences.

Subject.rent ();
Subject.hello ("World");

Here is a proxy object to invoke the implementation of the interface method, this time the program will jump to the proxy object associated with the handler invoke method to execute, and our handler object has accepted a realsubject type of parameters, This is the real object that I want to proxy, so I'm going to call the Invoke method in handler to do it:

public object Invoke (Object object, method method, object[] args)            throws Throwable    {        // We can add some of our own operation        System.out.println ("before Rent House") before acting on the real object.                System.out.println ("Method:" + method);    when a contemporary object invokes a method of a real object, it automatically jumps to the proxy object's associated handler object's Invoke method to invoke        Method.invoke (subject, args);                We can also add some of our own operation        System.out.println ("After the Rent house") when acting on the real object.                return null;    }

We see that we can add some of our own operations before and after the method that actually invokes the real object through the proxy object, and we see that we have a method object like this:

public abstract void Com.xiaoluo.dynamicproxy.Subject.rent () public abstract void Com.xiaoluo.dynamicproxy.Subject.hello (java.lang.String)

Exactly the two methods in our subject interface, which proves that when I invoke a method through a proxy object, it is actually called by the Invoke method of the handler object to which the delegate is associated, not by itself, but by proxy.

This is our Java Dynamic Agent mechanism.

This essay explains in detail the dynamic agent mechanism in Java, the knowledge point is very important, including our spring AOP is implemented through the mechanism of dynamic proxy, so we must understand the mechanism of dynamic agent.

Summarize

A typical dynamic agent creation process can be divided into the following four steps:
1. Create your own call processor by implementing the Invocationhandler interface Ivocationhandler handler = new Invocationhandlerimpl (...);
2. Create a dynamic proxy class by specifying a ClassLoader object and a set of interface for the proxy class
Class clazz = Proxy.getproxyclass (classloader,new class[]{...});
3. Obtain the constructor of the dynamic proxy class through the reflection mechanism, whose parameter type is the calling processor interface type
Constructor Constructor = Clazz.getconstructor (New Class[]{invocationhandler.class});
4, create the proxy class instance through the constructor function, at this time the call processor object should be passed as a parameter
Interface Proxy = (Interface) constructor.newinstance (new object[] (handler));
In order to simplify the object creation process, the Newinstance method in the proxy class encapsulates two steps to complete the creation of the proxy object.
The generated proxysubject inherits the proxy class implementation of the subject interface, and the implementation of the subject method actually invokes the handler's Invoke method, whereas the Invoke method uses reflection to invoke the method of the Proxied object (object result= Method.invoke (Proxied,args))

Ointment

Admittedly, theproxy has been designed to be very graceful, but there is a little bit of regret, that is, it has always been unable to get rid of the shackles only support interface Agent, because its design doomed this regret. Recall the inheritance diagram of dynamically generated proxy classes, which are already destined to have a common parent class called proxy. Java's inheritance mechanism is doomed to these dynamic proxy classes can not implement the dynamic proxy class, because the multi-inheritance in Java is inherently unworkable. There are a number of reasons why people can negate the need for class proxies, but there are also some reasons to believe that supporting a class dynamic agent will be better. Interface and class division, this is not very obvious, but in Java only to become so refined. If you only consider the declaration of a method and whether it is defined, there is a mixture of the two, its name is abstract class. The realization of the dynamic agent of the abstract class, believe also has its intrinsic value. In addition, there are some legacy classes that will never ever be associated with dynamic proxies because they do not implement any interfaces. So many, have to say is a small regret. However, imperfect is not equal to not great, great is an essence, Java Dynamic Agent is an example.

[Reprint] Java dynamic agent mechanism of the detailed

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.