Learn Java proxy mode, this one is enough

Posted by Chris.P on Fri, 19 Jun 2020 11:36:09 +0200

This article will explain the agent mode through its concept, characteristics, and finally realize the use scenarios of each agent mode through coding.

What is agent mode

Agent pattern is a programming design pattern in Java language. There are two important roles: the principal class and the agent class. The agent class can call the delegate class and extend the existing functions of the delegate class.

How to understand this model? The common things in daily life are as follows:

The landlord gives the house he needs to rent to the real estate agent to help him manage the complicated process including taking the tenant to see the house, signing the contract, etc. the landlord only needs to obtain benefits through the house at last. In this case, the landlord is the principal and the real estate intermediary is the agent.

In Java development, agents are divided into static agents and dynamic agents.

Dynamic agents are divided into jdk dynamic agents and cglib dynamic agents.

Characteristics of static agent and dynamic agent

Static agent

Advantage: it can add new functions through proxy class without modifying the code of delegate class.

Disadvantages: both the delegate class and the proxy class implement the interface of the parent class. Once the interface code of the parent class changes, both the delegate class and the proxy class need to maintain the code.

Dynamic agent

The jdk agent in dynamic agent can solve that shortcoming in static agent. The proxy class of jdk dynamic proxy does not need to implement the parent interface, but the delegate class needs to implement the parent interface.

It not only simplifies the programming work, but also improves the scalability of the software system.

The above static agent and jdk dynamic agent must let the delegate class implement the parent interface. If the delegate class does not implement any interface, the two agent modes will not work, so the cglib dynamic agent will be on top.

Code to implement static agent

Interface of parent class

/**
 * Interface of parent class
 * @author Yang 33
 * @date 2020/6/18 19:48
 */
public interface ParentInterface {
    /**
     * Ways to make money
     */
    void money();
}

Entrustment: Landlord

/**
 * Client: Landlord
 * @author Yang 33
 * @date 2020/6/18 19:20
 */
public class Owner implements ParentInterface {
    /**
     * How landlords make money
     */
    public void money() {
        System.out.println("Landlord: it's comfortable to lie down and earn money...");
    }
}

Agent class: mediation

/**
 * Agent class: mediation
 * @author Yang 33
 * @date 2020/6/18 19:45
 */
public class Medium implements ParentInterface {
    //Introduce the landlord object and connect with the intermediary
    private Owner owner;
    public Medium(Owner owner) {
        this.owner = owner;
    }

    /**
     * The agent class extends the existing functions of the agent class
     */
    public void money() {
        System.out.println("Intermediary: lead clients to look around...");
        System.out.println("Agent: sit down and negotiate with the client to sign the rental contract...");
        //Tell the landlord it's money
        owner.money();
    }
}

Test method:

/**
 * @author Yang 33
 * @date 2020/6/18 19:54
 */
public class Demo {
    public static void main(String[] args) {
        //Delegation class
        Owner owner = new Owner();
        //proxy class
        Medium medium = new Medium(owner);
        medium.money();
    }
}

Print results of running test method:

Intermediary: leading customers around to see the house
 Agent: sit down and sign a rental contract with the client
 Landlord: it's comfortable to lie down and earn money

Coding for jdk dynamic proxy

The jdk dynamic Proxy must be used in the Java API, java.lang.reflect The Proxy class and InvocationHandler interface in the package.

Modify the agent class in the above static agent as follows:

import java.lang.reflect.Proxy;

/**
 * Agent class: mediation
 * @author Yang 33
 * @date 2020/6/18 19:45
 */
public class Medium {
    //Introduce delegate class and associate with proxy class
    private Object object;
    public Medium(Object object) {
        this.object = object;
    }

    /**
     * The agent class extends the existing functions of the agent class
     */
    public Object getProxyInstance() {
        return Proxy.newProxyInstance(
                object.getClass().getClassLoader(),
                object.getClass().getInterfaces(),
                new InvocationHandler() {
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("Intermediary: lead clients to look around...");
                        System.out.println("Agent: sit down and negotiate with the client to sign the rental contract...");
                        //Tell the landlord it's money
                        Object invoke = method.invoke(object, args);
                        return invoke;
                    }
                }
        );
    }
}

Test method:

/**
 * @author Yang 33
 * @date 2020/6/18 19:54
 */
public class Demo {
    public static void main(String[] args) {
        //Delegation class
        ParentInterface owner = new Owner();
        //proxy class
        ParentInterface proxyInstance = (ParentInterface)new Medium(owner).getProxyInstance();
        proxyInstance.money();
    }
}

Print results of running test method:

Agent: lead clients to look around
 Agent: sit down and sign a rental contract with the client
 Landlord: it's comfortable to lie down and earn money

Implementation of cglib dynamic proxy by coding

Using cglib dynamic agent, we need to introduce dependency into maven project

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

Delegate class, does not implement any interface

/**
 * Entrustment: Landlord
 * @author Yang 33
 * @date 2020/6/18 19:20
 */
public class Owner {
    /**
     * How landlords make money
     */
    public void money() {
        System.out.println("Landlord: it's comfortable to lie down and earn money...");
    }
}

Proxy class:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * cglib Proxy subclass of
 * @author Yang 33
 * @date 2020/6/18 19:45
 */
public class Medium implements MethodInterceptor {
    //Introduce delegate class and associate with proxy class
    private Object object;
    public Medium(Object object) {
        this.object = object;
    }

    /**
     * Create proxy class
     */
    public Object getProxyInstance() {
        Enhancer en = new Enhancer();
        //Set the bytecode of the delegate class
        en.setSuperclass(object.getClass());
        //Set callback function
        en.setCallback(this);
        //Create proxy class
        return en.create();
    }

    public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Intermediary: lead clients to look around...");
        System.out.println("Agent: sit down and negotiate with the client to sign the rental contract...");
        //Tell the landlord it's paid
        Object invoke = method.invoke(object, args);
        return invoke;
    }
}

Test method:

/**
 * @author Yang 33
 * @date 2020/6/18 19:54
 */
public class Demo {
    public static void main(String[] args) {
        //Delegation class
        Owner owner = new Owner();
        //proxy class
        Owner proxyInstance = (Owner)new Medium(owner).getProxyInstance();
        proxyInstance.money();
    }
}

Print results of running test method:

Agent: lead clients to look around
 Agent: sit down and sign a rental contract with the client
 Landlord: it's comfortable to lie down and earn money

summary

Static proxy requires both the delegate class and the proxy class to implement the same interface or inherit the same parent class.

jdk dynamic proxy class needs to implement interface or inherit parent class, but proxy class does not need.

Neither the proxy class nor the proxy class of cglib dynamic proxy need to implement the interface or inherit the parent class.

Link to the original text:

Source network, only for learning, if there is infringement, please contact delete.

I have compiled the interview questions and answers into PDF documents, as well as a set of learning materials, including Java virtual machine, spring framework, java thread, data structure, design pattern, etc., but not limited to this.

Focus on the official account [java circle] for information, as well as daily delivery of quality articles.

file

Topics: Programming Java JDK Maven