Dynamic agent mode

Posted by wildcolour on Tue, 21 Dec 2021 03:18:45 +0100

Proxy pattern is a common design pattern in Java development. The design purpose is to insert other functions between service class and customer class. The inserted functions are transparent to the caller and play the role of camouflage control

1. Static proxy mode

Characteristics of static agent

1. Target role fixed

2. Get the target role before the application executes

3. Proxy objects enhance the behavior of the target object (add some methods)

4. It is possible that there are multiple proxies causing a "class explosion" (disadvantage)

Class explosion, add code for a delegate object.

Interface

public interface Abstract1 {
    void getGoods1();
}
public interface Abstract2 {
    void getGoods2();
}

Delegate class

public class Delegate01 implements Abstract1 {
    public void getGoods1() {
        System.out.println("GOODs1 Buying...");
    }
}
public class Delegate02 implements Abstract2{
    public void getGoods2() {
        System.out.println("Goods2 Buying...");
    }
}

Static proxy class

/**
 * The more delegates you implement, the more redundant your classes become
 */
public class StacicProxy implements Abstract1,Abstract2{
    private Delegate01 delegate01;
    private Delegate02 delegate02;

    public StacicProxy(Delegate01 delegate01, Delegate02 delegate02) {
        this.delegate01 = delegate01;
        this.delegate02 = delegate02;
    }

    public void getGoods1() {
        beforePreprocessor();
        delegate01.getGoods1();
        afterPreprocessor();
    }

    public void getGoods2() {
        beforePreprocessor();
        delegate02.getGoods2();
        afterPreprocessor();
    }
    private void beforePreprocessor(){
        System.out.println("Find a special agent..");
    }
    private void afterPreprocessor(){
        System.out.println("Transaction completed..");
    }
}

Customer class

public class Client {
    public static void main(String[] args) {
        Delegate01 delegate01 = new Delegate01();
        Delegate02 delegate02 = new Delegate02();
        StacicProxy proxy = new StacicProxy(delegate01,delegate02);
        proxy.getGoods1();
    }
}

Dynamic agent

Compared with static proxy, dynamic proxy is more flexible in creating proxy objects. The bytecode of dynamic proxy class is dynamically generated by Java reflection mechanism when the program is running. It will dynamically create proxy objects for the target object during the program run-time through the reflection mechanism, without the need for programmers to write its source code manually. Dynamic agent not only simplifies programming, but also improves the scalability of software system, because reflection mechanism can generate any type of dynamic agent class. The behavior of an agent can represent multiple methods, which not only meets the needs of production, but also achieves the purpose of common code.

Two implementations of dynamic agent:

  1. JDK dynamic agent

  2. CGLIB dynamic proxy

Characteristics of dynamic agent
1. The target object is not fixed
2. The target object is created dynamically as the application executes
3. Proxy objects enhance the behavior of the target object

DynamicProxy(JDK)

public class DynamicProxy implements InvocationHandler {
    //Proxy object
    private Object delegate;

    public Object getDelegate() {
        return delegate;
    }

    public void setDelegate(Object delegate) {
        this.delegate = delegate;
    }
    //Pre enhancement
    private void beforePreprocessor(){
        System.out.println("Find a special agent..");
    }
    //Post enhancement
    private void afterPreprocessor(){
        System.out.println("Transaction completed..");
    }

    //Get dynamic Proxy object through Proxy
    public Object getProxyInstance(){
       return Proxy.newProxyInstance(delegate.getClass().getClassLoader(),delegate.getClass().getInterfaces(),this);
    }

    //Method enhancement through dynamic proxy objects
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        beforePreprocessor();
        Object ret = method.invoke(delegate, args);
        afterPreprocessor();
        return ret;
    }
}

DynamicProxy (Cglib)

	<dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>2.2.2</version>
	 </dependency>
public class DynamicProxy2 implements MethodInterceptor {
    //Proxy object
    private Object delegate;

    public Object getDelegate() {
        return delegate;
    }

    public void setDelegate(Object delegate) {
        this.delegate = delegate;
    }
    //Pre enhancement
    private void beforePreprocessor(){
        System.out.println("Find a special agent..");
    }
    //Post enhancement
    private void afterPreprocessor(){
        System.out.println("Transaction completed..");
    }

    //Get dynamic Proxy object through Proxy
    public Object getProxyInstance(){
        // A class can be generated by the create() method of the Enhancer object to generate a proxy object
        Enhancer enhancer = new Enhancer();
        // Set parent class (with target class as its parent)
        enhancer.setSuperclass(delegate.getClass());
        // Set the interceptor callback object as its own object
        enhancer.setCallback(this);
        // Generate a proxy class object and return
        return enhancer.create();
    }

    //Method enhancement through dynamic proxy objects
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        beforePreprocessor();
        Object ret = methodProxy.invoke(delegate, objects);
        afterPreprocessor();
        return ret;
    }
}

Client

public class Client {
    public static void main(String[] args) {
        //Delegate class 1
        Delegate01 delegate01 = new Delegate01();
        //Delegate class 2
        Delegate02 delegate02 = new Delegate02();

        //Dynamic proxy class
//        DynamicProxy dynamicProxy = new DynamicProxy();
        DynamicProxy2 dynamicProxy = new DynamicProxy2();

        //On entrustment 1
        dynamicProxy.setDelegate(delegate01);
        Abstract1 proxyInstance = (Abstract1)dynamicProxy.getProxyInstance();
        proxyInstance.getGoods1();
        System.out.println("========================================");
        //On entrustment 2
        dynamicProxy.setDelegate(delegate02);
        Abstract2 proxyInstance2 = (Abstract2)dynamicProxy.getProxyInstance();
        proxyInstance2.getGoods2();
    }
}

Differences between JDK agent and CGLIB agent

1,JDK Dynamic proxy implementation interface, Cglib Dynamic agent inheritance
2,JDK The execution efficiency of dynamic proxy (when the target object has an interface) is higher than Ciglib
3,If the target object has an interface implementation, select JDK Proxy, if there is no interface implementation option Cglib agent

Topics: Design Pattern AOP Proxy