JAVA proxy mode


Java agents are divided into static agents and dynamic agents. Dynamic agent is divided into JDK dynamic agent and cglib dynamic agent. In terms of various performance tests, JDK is better than cglib. It is strongly recommended to master the agent mode, interview high-frequency questions, and use the concept of aspect oriented programming (AOP).

Static proxy

Define an interface or parent class. The proxy object and the proxy object implement the same interface or inherit the same parent class

Code example:

Create User interface:

public interface User {
    void show();
}

Create User interface implementation class userimpl java

public class UserImpl implements User {
    @Override
    public void show() {
        System.out.println("realization Java Static proxy");
    }
}

Create proxy class proxy java

/**
 * Static proxy mode
 * You must create a proxy class
 * Proxy mode provides a proxy object for an object, and the proxy object controls the reference to the original object.
 *
 */
public class Proxy implements User {
    private User user;

    //Constructor
    public Proxy(final User user){
        this.user=user;
    }
    
    @Override
    public void show() {
        System.out.println("Insert logical code before code execution");
        user.show();
        System.out.println("Insert logical code after code execution");
    }
}

Create test class

public class Test {
    public static void main(String[] args) {

        User user = new UserImpl();
        Proxy proxy = new Proxy(user);
        proxy.show();

    }
}

Operation results:

JDK dynamic agent

JDK dynamic proxy uses reflection mechanism to create proxy class at runtime. The core is InvocationHandler. Each instance of an agent has an associated invocation handler. When a proxy instance is to be called, the method's call is encoded and assigned to the invoke method of its invocation handler. Therefore, all calls to proxy object instance methods are completed through the invoke method in InvocationHandler, and the invoke method will determine which proxy method to call according to the passed proxy object, method name and parameters.

Create User interface

public interface User {
    void show();
}

Create User interface implementation class userimpl java

public class UserImpl implements User{
    @Override
    public void show() {
        System.out.println("realization JDK Dynamic agent");
    }
}

Create proxy class myproxyhandler java

Proxy. The newproxyinstance() method accepts three parameters:

  • Classloader: Specifies the class loader used by the current target object. The method to obtain the loader is fixed
  • Class<?> [] interfaces: specify the type of interface implemented by the target object, and confirm the type using generic method
  • InvocationHandler: Specifies the dynamic processor. When executing the method of the target object, the method of the event handler will be triggered
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyProxyHandler implements InvocationHandler {

    private Object object;

    public MyProxyHandler(final Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Insert logical code before code execution");
        Object result = method.invoke(object, args);
        System.out.println("Insert logical code after code execution");
        return result;
    }
}

Create test class

public class Test {
    public static void main(String[] args) {
        
        User user = new UserImpl();
        User o1 = (User) Proxy.newProxyInstance(user.getClass().getClassLoader(),
                new Class[]{User.class}, new MyProxyHandler(user));
        o1.show();

    }
}

Operation results:

cglib dynamic proxy

CGLib adopts very low-level bytecode technology. Its principle is to create a subclass for a class through bytecode technology, and use the method interception technology in the subclass to intercept the calls of all parent class methods, so as to weave cross cutting logic. JDK dynamic proxy and CGLib dynamic proxy are the basis for implementing Spring AOP.

pom. Import Maven dependency from XML file

<dependencies>
     <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
     </dependency>
</dependencies>

Create User class

public class User {
    public void show(){
        //In actual development, this is the code for logical business development
        System.out.println("realization cglib Dynamic agent");
    }
}

Create proxy class myproxy java

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class MyProxy implements MethodInterceptor {
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("You can insert logical code before code execution");
        Object o1 = methodProxy.invokeSuper(o,objects);
        System.out.println("You can insert logical code after code execution");
        return o1;
    }
}

Create test class

import net.sf.cglib.proxy.Enhancer;

public class Test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();  // The process of obtaining proxy objects through CGLIB dynamic proxy
        enhancer.setSuperclass(User.class);     // Sets the parent class of the enhancer object
        enhancer.setCallback(new MyProxy());    // Sets the callback object for enhancer
        User user = (User) enhancer.create();   // Create proxy object
        user.show();  // Call the target method through the proxy object
    }
}

Operation results:

summary

Static agent summary:

(1) In fact, the so-called static proxy is to create a class called proxy class, and then the class implements the same interface as the target class business layer object,
Rewrite the interface content to do enhanced business, that is, user-defined operations, and then call the method of the injected target class [i.e. business layer object] when it is necessary to execute the method of the target class,
To put it bluntly, it is just a set of methods outside the target class.
(2) The purpose of rewriting is to ensure that the methods of the target class are the same. It can not only ensure that there is no mistake, but also do not need to write by hand, which is very comfortable,
However, it does not mean that the target class must have an interface to use a static proxy. Therefore, the target class can use a static proxy whether it has an interface or not.
(3) Disadvantages: because the proxy object needs to implement the same interface as the target object, there will be too many proxy classes. At the same time, once the interface adds methods, both the target object and the proxy object must be maintained.

JDK dynamic agent summary:

(1) Dynamic proxy solves the disadvantage of static proxy. The proxy class does not need to implement the same interface as the target object.
(2) after the instance agent class is injected, the object class object can be injected. Then the proxy class method is invoked to create the proxy object dynamically in memory. After [using Proxy.newProxyInstance], return the proxy object, and then forcibly convert it to the same type as the target object. You can call the method according to the target type. The parameters you need to enter to create the proxy object are the class loader of the target class, the class type of the interface implemented by the target object, and the event handler. Then rewrite the method in the event handler, and write custom in the method The method call of the target object uses object returnValue = method Invoke (target, args) completed.
(3) Although the proxy class does not directly implement the interface implemented in the target class, the injection parameters of dynamically creating proxy object methods in memory need the type of interface implemented by the target object. Therefore, the target class must implement at least one interface, otherwise the dynamic proxy cannot be used.
(4) Disadvantages: some classes are not in the business layer. They are just a separate class and do not implement any interfaces. Dynamic agents cannot be used.

CGLib agent summary:

(1) Remember to import the cglib dependency package, which is actually a code generation package. Build a subclass object in memory to extend the function of the target object.
(2) The proxy class needs to implement the MethodInterceptor interface to rewrite the interception method [intercept()]. The internal enhanced operation mode is very similar to that of JDK dynamic proxy.
(3) To create a proxy object, you need to use the tool class Enhancer.
(4) Allowing proxy to target classes that do not implement any interfaces solves the disadvantage of dynamic proxy.
(5) The bottom layer is ASM bytecode framework. It is not recommended to directly operate ASM.

Keywords: Python Java Spring Design Pattern AOP

Added by Begbie on Mon, 03 Jan 2022 08:31:03 +0200