Spring learning -- proxy mode

Posted by coco777 on Fri, 31 Dec 2021 09:17:13 +0100

Spring learning source code: https://download.csdn.net/download/qq_41505957/20606092

proxy pattern

Proxy mode:

  • Static proxy
  • Dynamic agent
Static proxy

Example: the customer wants to rent a house, and the landlord wants to rent a house,

Landlord. The landlord wants to rent the house.

public class Landlord {
    public void rent() {
        System.out.println("The landlord wants to rent the house!");
    }
}

Customera.java customers want to rent a house, so they only need to create a landlord class and call the landlord class's rent method.

public class Customer {
    public static void main(String[] args) {
        Landlord landlord = new Landlord();
        landlord.rent();
    }
}

Static agent role analysis

  • Abstract role: generally implemented using interfaces or abstract classes
  • Real role: the role represented
  • Agent role: agent real role; After representing a real role, you usually do some ancillary operations
  • Customer: use the agent role to perform some operations

Use the agent model to separate the abstract role of renting. Now customers don't go to the landlord, but to the intermediary. In this process, the intermediary will have ancillary operations.

Abstract role: rent a house

//Abstract role: rent a house
public interface Lease {
    public void rent();
}

Real role: landlord, the landlord wants to rent the house

//Real role: landlord, the landlord wants to rent the house
public class Landlord implements Lease {
    public void rent() {
        System.out.println("The landlord wants to rent the house!");
    }
}

Acting role: intermediary, acting as the landlord to rent out the house

//Agent role
public class Intermediary implements Lease{
    private Landlord landlord;

    public Intermediary(Landlord landlord) {
        this.landlord = landlord;
    }

    public void rent() {
        this.landlord.rent();
        kanfang();
        hetong();
        shouqian();
    }

    public void kanfang() {
        System.out.println("Intermediary: showings");
    }

    public void hetong(){
        System.out.println("Intermediary: signing contract");
    }

    public void shouqian() {
        System.out.println("Intermediary: collect money");
    }
}

Customer: rent a house

//customer
public class Customer {
    public static void main(String[] args) {
        Intermediary intermediary = new Intermediary(new Landlord());
        intermediary.rent();
    }
}

Now customers want to rent a house and go directly to an intermediary. The intermediary will rent the house on behalf of the landlord. At the same time, the intermediary will have ancillary operations.

Benefits of static agents:

  • It can make our real role more pure Stop paying attention to some public things
  • Public business is done by agents The division of business is realized,
  • When the public business expands, it becomes more centralized and convenient

Disadvantages:

  • With more classes and more proxy classes, the workload becomes larger Reduced development efficiency

We want the benefits of static agent, but we don't want the disadvantages of static agent, so we have dynamic agent!

Static agent re understanding

Create an abstract class with the business of adding, deleting, modifying and querying

public interface UserService {
    void add();
    void delete();
    void update();
    void query();
}

Implementation class

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("Add user");
    }

    public void delete() {
        System.out.println("delete user");
    }

    public void update() {
        System.out.println("Update user");
    }

    public void query() {
        System.out.println("Query user");
    }
}

Call method:

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        userService.add();
    }
}

Now if you want to add a log function, if you modify the original code directly, the structure of the code will be changed, which can be implemented in agent mode.

Add a proxy class:

public class UserServiceProxy implements UserService{
    private UserServiceImpl userServiceImpl;

    public UserServiceProxy(UserServiceImpl userServiceImpl) {
        this.userServiceImpl = userServiceImpl;
    }

    public void add() {
        log("add");
        userServiceImpl.add();
    }

    public void delete() {
        log("delete");
        userServiceImpl.delete();
    }

    public void update() {
        log("update");
        userServiceImpl.update();
    }

    public void query() {
        log("query");
        userServiceImpl.query();
    }

    public void log(String method){
        System.out.println("call" + method +"method");
    }
}

Call method

public class Client {
    public static void main(String[] args) {
        UserServiceProxy userServiceProxy = new UserServiceProxy(new UserServiceImpl());
        userServiceProxy.add();
    }
}

Dynamic agent

Lease.java

//Abstract role: rent a house
public interface Lease {
    public void rent();
}

Landlord.java

//Real role: landlord, the landlord wants to rent the house
public class Landlord implements Lease {
    public void rent() {
        System.out.println("The landlord wants to rent the house!");
    }
}

The getProxy() method returns the proxy class we need

public class ProxyInvocationHandler implements InvocationHandler {

    private Lease lease;

    public void setLease(Lease lease) {
        this.lease = lease;
    }
    //Generate an agent class, focusing on the second parameter to obtain the abstract role to be represented! It used to be a role, but now it can represent a kind of role
    public  Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),lease.getClass().getInterfaces(),this);
    }

    // Proxy: proxy class method: the method object of the calling handler of the proxy class
    // Process method calls on proxy instances and return results
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(lease,args);
        return result;
    }
}
public class Client {
    public static void main(String[] args) {
        //Real role
        Landlord landlord = new Landlord();
        //Call handler for proxy instance
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        pih.setLease(landlord);//Put the real character in!
        Lease lease = (Lease) pih.getProxy();//Dynamically generate the corresponding proxy class!
        lease.rent();
    }
}

Output results:

If there are additional operations, you only need to add the operations to be executed in the invoke method.

public class ProxyInvocationHandler implements InvocationHandler {

    private Lease lease;

    public void setLease(Lease lease) {
        this.lease = lease;
    }
    //Generate an agent class, focusing on the second parameter to obtain the abstract role to be represented! It used to be a role, but now it can represent a kind of role
    public  Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),lease.getClass().getInterfaces(),this);
    }

    // Proxy: proxy class method: the method object of the calling handler of the proxy class
    // Process method calls on proxy instances and return results
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(lease,args);
        kanfang();
        hetong();
        shouqian();
        
        return result;
    }
    public void kanfang() {
        System.out.println("Intermediary: showings");
    }

    public void hetong(){
        System.out.println("Intermediary: signing contract");
    }

    public void shouqian() {
        System.out.println("Intermediary: collect money");
    }
}

Output results:

To change the code to a general class, you only need to change Lease in the code to Object.

public class ProxyInvocationHandler implements InvocationHandler {

    private Object obj;

    public void setObj(Object obj) {
        this.obj = obj;
    }

    //Generate an agent class, focusing on the second parameter to obtain the abstract role to be represented! It used to be a role, but now it can represent a kind of role
    public  Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
    }

    // Proxy: proxy class method: the method object of the calling handler of the proxy class
    // Process method calls on proxy instances and return results
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(obj,args);
        kanfang();
        hetong();
        shouqian();
        return result;
    }
    public void kanfang() {
        System.out.println("Intermediary: showings");
    }

    public void hetong(){
        System.out.println("Intermediary: signing contract");
    }

    public void shouqian() {
        System.out.println("Intermediary: collect money");
    }
}

Benefits of dynamic agents:

  • It can make our real role more pure Stop paying attention to some public things
  • Public business is done by agents The division of business is realized,
  • When the public business expands, it becomes more centralized and convenient
  • A dynamic agent, generally acting for a certain kind of business
  • A dynamic proxy can proxy multiple classes, and the proxy is the interface!

Topics: Java Spring