Java static agents, JDK dynamic proxies and dynamic proxy CGLIB

Use a proxy has two advantages, one can hide the implementation delegate class; the second is to achieve decoupling between the client and the delegate class, without modifying the code of the delegate class can do some additional processing.

Give a very common example. Factory will produce lots of toys, but we all buy toys to the store to buy, not to buy the factory, the factory production we do not care how, we only know that the store can buy the toy they want, and, If we need to give it away, then store these toys can also use gift boxes packaging. Here, this plant is commissioned class, is the agent class shops, we are the type of customers, some additional processing gift box is a proxy class for the delegate class to do.

There are many scenarios need to use a proxy class, such as when a remote RPC call is through a proxy class to implement, as well as the Spring AOP aspects, we also generate a proxy class for the cut and so on in Java.

Acting classes are divided into static agents, JDK dynamic proxies and CGLIB dynamic proxy, they have their own advantages and disadvantages, not the best, there is significant under different scenarios they have different purposes.

Java static proxy

Static agent first is to define the interface and the interface implementation class, and then define the interface proxy object, and inject instance of an interface to the proxy object, and then to call the real implementation class through a proxy object, the implementation process is very simple and easy to understand. Static agent during compilation of the agency relationship has been identified, the less suitable proxy class and determine the case, you can do some additional processing to achieve without modifying the delegate class, such as packing boxes, to achieve customer class and delegate decoupling or any such thing. But the drawback is that only applies to the next few delegate method situation, imagine if there are hundreds of thousands of delegate class methods, are we going to write a bunch of proxy methods in the proxy class, so there is a dynamic proxy to solve this problem, dynamic agency said later.

Define the interface implementation class and interfaces

Interface delegate //
public interface SayHelloService {
    void the sayHello (String the userName);
}

 

// 委托实现类
public class SayHelloServiceImpl implements SayHelloService {
    public void sayHello(String userName) {
        System.out.println("hello, " + userName);
    }
}

 

Acting class interface

 

// 代理类
public class SayHelloProxy implements SayHelloService {
    private SayHelloService sayHelloService = new SayHelloServiceImpl();

    void sayHello public (String userName) {
        // do something beforehand proxy
        System.out.println ( "do something before proxy ... ");

        // call the method delegate class
        sayHelloService.sayHello (userName);

        // do something afterwards proxy
        System.out.println ( "do something the After Proxy ...");
    }
}

 

Object Access through a proxy delegate class

 

// 测试静态代理类
public class SayHelloTest {
    public static void main(String[] args) {
        SayHelloProxy sayHelloProxy = new SayHelloProxy();
        sayHelloProxy.sayHello("yanggb");
    }
}

 

Java's dynamic proxy technology

Agent proxy class created in the way the program is running, it is called dynamic proxy. In understanding the dynamic agent, first review three things JVM loading phase of class loading mechanisms need to do:

1 to obtain a binary byte stream by the full name of the class or a class of other ways.

2. The byte stream represents static storage structure into a run-time data structure area method.

3. In the memory generates a representative of this class Class object, as a method for the inlet zone of this type of access.

Dynamic agent mainly took place in the first stage, the source of a binary byte stream at this stage can have many classes, such as ZIP package, the network calculates and generates run-time, the file generating other (JSP), and the like acquired database. Java is calculated to generate a dynamic agent operating technique wherein when, in the Proxy class, is to use a ProxyGenerator.generateProxyClass to generate a specific form of the interface class Proxy Agent * $ binary byte stream. The so-called dynamic proxy is to find ways to calculate the proxy class bytecode is then loaded into the JVM in The interface or audiences. Calculation of the actual situation will be very complicated, it is generally by means of some, such as JDK dynamic proxy implementation, CGLIB third-party libraries to complete. Therefore, to make proxy class generated by the target object (that is, the delegate class) consistency, usually there are two ways: by JDK dynamic proxy interface and by CGLIB dynamic proxy class inheritance.

As said earlier, reflecting both dynamic proxies are based to achieve, look at run-time object properties, methods, modify the scope, method name by calling methods. The online application will not use frequently reflected as reflected greater performance overhead, so in addition to using the ASM framework JAVASSIST, relatively little overhead, with additional space next to say.

JDK dynamic proxies

In the Java JDK dynamic proxy, mainly related to two classes, one java.lang.reflect.Proxy, one is java.lang.reflectInvocationHandler. To use the JDK dynamic proxy need an implementation InvocationHandler middle class interface, this interface has only one method invoke () method, a call to all methods of treatment classes will become a call to invoke () method, so that you can invoke ( ) the method of adding a unified processing logic (also according to the method based on which parameter method). Intermediate class (class implements InvocationHandler) has a delegate object reference, and call the appropriate methods in the class object delegate invoke () method, a delegate class object reference held by way of such polymerization, to the outside invoke () the final method calls are converted to calls to the delegate object.

In fact, the middle class and delegate class constitutes a static agent relationship, in this relationship, the middle class is the proxy class, class is a delegate delegate class. Then the proxy class and the middle class also forms a static agent relationship, in this relationship, the middle class is a delegate class, proxy class is a proxy class. In other words, dynamic agency relationship is a relationship between two static agent composition, which is JDK dynamic proxy principle.

Description parameters define the source (in comments) interface of InvocationHandler

 

interface of InvocationHandler {public
    / **
    * calling process
    * @param proxy agent class object
    * @param methon which identifies a specific calling method proxy class
    parameter * @param args proxy class method
    * /
    public Object Invoke (Object Proxy, Method, Method, Object [] args) throws the Throwable;
}

 

Define the interface implementation class and interfaces

 

// delegate class interface
public interface the HelloService {
    void the sayHello (String the userName);

    void sayByeBye(String userName);
}

 

 

// 委托类
public class HelloServiceImpl implements HelloService {
    public void sayHello(String userName) {
        System.out.println("hello, " + userName);
    }

    public void sayByeBye(String userName) {
        System.out.println("byebye, "+ userName);
    }
}

 

Define a class of intermediary interface InvocationHandler

 

// middle class
public class HelloInvocationHandler the implements InvocationHandler {
    / **
    * commissioned by the middle class holds a reference to the class object, where would constitute a static proxy relationship
    * /
    Private Object obj;

    / **
    * There argument constructor, the object passed delegate class
    *
    * @param obj delegate class objects
    * /
    public HelloInvocationHandler (Object obj) {
        this.obj = obj;
    }

    / **
    * proxy class dynamically generated objects, the Proxy.newProxyInstance
    *
    * @return proxy class instance returned
    * /
    public Object 'newProxyInstance () {
        return the Proxy.newProxyInstance (
                // specified proxy object class loader
                obj.getClass (). getClassLoader (),
                // proxy object needs to implement an interface, you can specify multiple interfaces simultaneously
                obj.getClass () getInterfaces (),.
                the actual handler // method call, the proxy object method calls are forwarded to here
                this);
    }

    / **
    * @param Proxy proxy object
    * @param method proxy method
    parameter method * @param args
    * /
    @Override
    public Object invoke (Object Proxy, Method, Method, Object [] args) throws the Throwable {
        // do invoke before something
        System.out.println ( "do something the before the Invoke ...");
        // execute the Invoke
        Object Method.invoke the Result = (obj, args);
        // do something after the Invoke
        System.out.println ( " do something after invoke ... ");

        return result;
    }
}

 

By the middle class to access the delegate class

 

// 测试动态代理类
public class HelloTest {
    public static void main(String[] args) {
        HelloInvocationHandler helloInvocationHandler = new HelloInvocationHandler(new HelloServiceImpl());
        HelloService helloService = (HelloService) helloInvocationHandler.newProxyInstance();
        helloService.sayHello("yanggb");
        helloService.sayByeBye("yanggb");
    }
}

 

In the above test dynamic proxy class, we call newProxyInstance () method of the Proxy class to get a proxy class example. The proxy class implements the interface we specify, and will be distributed to the specified method invocation call processor. First method of obtaining exemplary proxy class through 'newProxyInstance (), then you can by the method of Example calling the proxy class proxy class calls to the method of the proxy class calls the intermediate class (class that implements the InvocationHandler interface) the invoke () method in invoke () method we call the corresponding method delegate class, and then add their own processing logic.

JDK dynamic proxy greatest feature is dynamically generated proxy class and delegate implement the same interface. JDK dynamic proxy is actually achieved through internal reflection (Proxy.newProxyInstance), which is an object known at runtime dynamic call its methods, and time of the call can also add some of their own logic.

CGLIB dynamic proxy

JDK dynamic proxy dependent interface, and when we do not like the interface only when you need to use another dynamic agent technology: CGLIB dynamic proxy. First CGLIB dynamic proxy is a third-party framework to achieve, need to introduce cglib package in Maven project:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>

CGLIB proxy is a proxy for the class to achieve, the principle is to generate a subclass of the class specified on the commission and override one of the ways to achieve business agent. Agent class object is created by the Enhancer class. CGLIB creation mode dynamic proxy class is:

1. Find all non-final public method on the target class (final method can not be rewritten).

2. The definition of these methods into bytecodes.

3. converting bytecode into a corresponding Class object proxy, the proxy class instance of the object is then obtained by reflection.

4. MethodInterceptor implement the interface, all methods for processing requests for the proxy class.

Define a simple class

 

// delegate class, is simply a class
public class HelloClass {
    public void the sayHello (String the userName) {
        System.out.println ( "Hello," + the userName);
    }

    public void sayByeBye(String userName){
        System.out.println("byebye, " + userName);
    }
}

 

Define an implementation class interceptor class MethodInterceptor

 

// HelloInterceptor intercepting calls for a method and a callback
public class HelloInterceptor the implements MethodInterceptor {
    / **
    * CGLIB enhanced class object, the object class is created by the proxy class Enhancer,
    * Enhancer is CGLIB bytecode enhancer, can easily to expand the class
    * /
    Private Enhancer Enhancer Enhancer new new = ();

    / **
    *
    * @param the proxy object obj
    * @param method proxy process
    parameters * @param args method
    * @param proxy CGLIB method of the proxy object
    * @return cglib Method object to produce an object used in place of using MethodProxy method call JDK than its direct execution method will improve efficiency
    * /
    public Object Intercept (Object obj, method method, Object [] args, MethodProxy Proxy) throws the Throwable {
        System.out.println ( "call before the method");
        Object proxy.invokeSuper = O (obj, args);
        System.out.println ( "after the method call");
        return O;
    }

    / **
    * dynamic proxies create a proxy object
    * @param c class name
    * /
    public Object 'newProxyInstance (Class C <?>) {
        // set the parent class of the proxy object produced, the type of reinforcement
        enhancer.setSuperclass (c);
        // definition of the logical object as active agent, required to achieve the current object interfaces MethodInterceptor
        enhancer.setCallback (the this);
        // create the target object with no parameters default constructor, which is a prerequisite to provide the proxy class constructor with no arguments method
        return enhancer.create ();
    }
}

 

By blocking access class delegate class

 

// 测试类
public class HelloTest {
    public static void main(String[] args) {
        HelloInterceptor helloInterceptor = new HelloInterceptor();
        HelloClass sayHelloClass = (HelloClass) helloInterceptor.newProxyInstance(HelloClass.class);
        sayHelloClass.sayHello("yanggb");
        sayHelloClass.sayByeBye("yanggb");
    }
}

 

The need for the proxy class, it is just a sub-class to dynamically generate method to cover a non-final, while the hook callback bindings custom interceptor. It is faster than in the performance JDK dynamic proxy. It is worth noting that we pass in the goal class as parent proxy class. Different from the JDK dynamic proxy, we can not create a proxy using the target object. CGLIB target object can only be created. In an example, the default constructor with no arguments is used to create the target object.

to sum up

1. static proxy easier to understand, to be a proxy class and proxy classes implement the same interface from, then call the real implementation class in the proxy class, and the static agent relationship during compilation have been identified. The dynamic proxy relationship is determined during operation. Static proxy simple, suitable for small proxy class and determine the case, and the dynamic proxy provides us with greater flexibility.

2.JDK dynamic proxy when the proxy class used in the program to call the proxy class object is actually created by the JVM, JVM passed in accordance with the business to achieve the object class and method names, dynamically create a class file and word of a proxy class bytecode execution engine, and then call the method by which the agent class object. We need to do is pre-designated proxy class, after calling operation can be.

3. Static and dynamic proxy agents are based interface, and for those who do not provide an interface simply provides in terms of implementation class, you can only choose CGLIB a dynamic proxy.

1 is inscribed: difference JDK dynamic proxy and proxy dynamic CGLIB

1.JDK dynamic proxy is a Java reflection to achieve, we must implement the interface to business class in order to generate a proxy object using this method.

ASM 2.CGLIB dynamic proxy based framework, implemented by subclassing traffic class.

3.JDK advantage of dynamic proxy is to minimize dependence, reduce dependence meant to simplify development and maintenance, and has its own JDK support. Can also be performed smoothly JDK version upgrade code is simple.

4. Based on the advantages of CGLIB framework is no need to implement the interface to achieve non-invasive proxy class, we simply operate like we care about, do not increase the workload for the other class, performance is relatively high.

2 face questions: Describe several implementations of proxy, and say the advantages and disadvantages

Acting can be divided into static and dynamic proxy agent, and the agent is divided into dynamic and JDK dynamic proxy CGLIB dynamic proxy.

Static proxy: proxy objects and actual objects inherit the same interface, point in the proxy object is an instance of the actual object, so that the external exposure is really a proxy object called a Real Object. The advantage is you can well protect the actual object of the business logic of external exposure, thereby improving safety. The disadvantage is that different interfaces have different proxy class implementation, it will be redundant.

Dynamic agent JDK: JDK dynamic proxy InvocationHandler only need to implement the interface, rewriting invoke () method will be able to complete the implementation of the agent, is the use of reflection type Proxyxx.class generate the proxy proxy class bytecode and generates an object. JDK dynamic proxy agent interface only reason why is because the proxy class itself has inherited the Proxy class, but Java is not allowed multiple inheritance, but allows multiple interfaces. The advantage is to solve the static proxy redundancy agency implementation class problem. The disadvantage is that JDK dynamic proxy interface-based design is implemented, it will throw an exception if there is no interface.

CGLIB dynamic proxy: As the only JDK dynamic proxy restrictions based interface design, but the case is not the interface, JDK way can not solve. CGLIB with a very bottom of the byte code technology, the principle is to create a subclass of the class bytecode technique, and the method call interception techniques to intercept all the parent class method in the subclass, the flow cross weaving logic to complete the dynamic proxy. DETAILED implementation is to achieve an interface and override MethodInterceptor Intercept () method, implemented by the callback class method Enhancer. But CGLIB time when creating a proxy object takes much more than the JDK, so for example because no single object is frequently used to create objects CGLIB more appropriate. Otherwise JDK dynamic proxy using more appropriate manner. Also, because CGLIB is a method to dynamically create subclasses used for the final approach is not possible proxy. Advantage is that no interface agent can be dynamic, and uses a byte-code enhancement technology, and performance. The disadvantage is that the technology is relatively more difficult to understand.

Guess you like

Origin www.linuxidc.com/Linux/2019-11/161505.htm