“This is the 18th day of my participation in the August Gwen Challenge.

1. What is the proxy mode

Background:

When a client cannot or does not want to directly access another object, it needs to find a mediator to help complete a task. This mediator is the proxy object. For example, you don’t have to go to the railway station to buy train tickets. You can buy them on 12306.cn or at train ticket sales agencies. For instance look for girlfriend again, look for nurse, look for a job to wait to be able to complete through looking for intermediary.

Definition of proxy mode:

  • For some reason you need to provide a proxy for an object to control access to that object. In this case, the access object is not suitable or cannot directly reference the target object, and the proxy object acts as an intermediary between the access object and the target object.

The purpose of the proxy pattern:

  • == Provides a proxy for other objects to control access to this object ==.

What the proxy mode does:

  • == solves the problem of accessing objects directly, for example, on a remote machine. In object-oriented systems, some object for some reason (such as the object creation overhead is very large, or some operations require safety control, or need to access) outside the process, will have direct access to caused a lot of trouble for the user or the system structure, during a visit to this object we can = = add an object to this access layer (middle) = =.

2. Advantages and disadvantages of the proxy model

The main advantages of the proxy model are:

  • Proxy mode plays an intermediary role and protects the target object between the client and the target object.
  • Proxy objects extend the functionality of target objects;
  • The proxy mode can separate the client from the target object, and the responsibility is clear, which reduces the coupling degree of the system to a certain extent and increases the scalability of the program

Its main disadvantages are:

  • The proxy pattern increases the number of classes in the system design
  • Adding a proxy object between the client and the target object slows down request processing.
  • Increased the complexity of the system;

So how to solve the disadvantages mentioned above? The answer is to use dynamic proxies

3. Structure of proxy mode

The main roles of the proxy mode are as follows.

  1. Abstract Subject class: Business methods that declare real subjects and proxy object implementations through the == interface or abstract class ==.
  2. Real Subject class: Implements the concrete business in an abstract topic, is the Real object represented by the proxy object, and is the object ultimately referenced (the role being propped).
  3. Proxy class: Provides the same interface as a real topic, with internal references to real topics that can access, control, or extend the functionality of real topics.
  4. Client class: The person who accesses the proxy class

Its structure is shown in the figure.

Let’s take an example of renting to understand the agency model

In this example, rental is abstract subject, real estate agent is agent, landlord is real subject, renter is client, landlord is real object represented by intermediary.

4. Classification of agent modes

According to the creation time of the agent, the agent mode can be divided into static agent and dynamic agent.

  • Static proxy: a programmer creates a proxy class or a specific tool automatically generates source code and compiles it. The.class file of the proxy class exists before the program runs.
  • Dynamic proxy: dynamically created using reflection while the program is running

4.1. Static Proxy

Static agent code to achieve rental:

1. The interface

/ / rent
public interface Rent {
    public void rent(a);
}
Copy the code

2. Real characters

// The landlord, the real role of the agent to achieve Rent interface
public class Host implements Rent{

    @Override
    public void rent(a) {
        System.out.println("The landlord is renting out the house."); }}Copy the code

3. Proxy role

package com.cheng.demo01;

// Broker broker
public class Proxy implements Rent{
    // Use more composition and less inheritance
    private Host host;

    public Proxy(a) {}public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent(a) {
        host.rent();
        seeHost();
        charge();
    }
    // To see a house, the agent can do this, but the landlord can not
    public void seeHost(a){
        System.out.println("Agent shows you the house.");
    }
    // Only intermediaries can do this
    public void charge(a){
        System.out.println("The agency charges you an intermediary fee."); }}Copy the code

4. The customer class

// People who want to rent a house
public class Client {
    public static void main(String[] args) {
        Host host = new Host();// Get the landlord
        // Since the landlord cannot rent the house directly, we need to find an agent to visit the landlord through the agent
        // The agent usually has some ancillary operations, such as viewing the house and collecting the agent fee
        Proxy proxy = new Proxy(host);
        proxy.rent();// Call the landlord's rent method}}Copy the code

Static proxy code implementation two:

1. Interface, only add, delete, change and check methods

// Abstract the role
public interface UserService {
    public void add(a);
    public void delete(a);
    public void update(a);
    public void query(a);
}
Copy the code

2. Real characters, realizing the method of adding, deleting, changing and checking

package com.cheng.demo02;

import java.util.Random;
// Real characters
public class UserServiceImpl implements UserService{

    @Override
    public void add(a) {
        System.out.println("Added a user.");
    }
    @Override
    public void delete(a) {
        System.out.println("Deleted a user");
    }
    @Override
    public void update(a) {
        System.out.println("Modified a user");
    }
    @Override
    public void query(a) {
        System.out.println("Query a user"); }}Copy the code

Requirement: If you want to print logs while executing methods in the interface without changing the original business code, the best way to do this is to use static proxies.

3. The proxy class

package com.cheng.demo02;
/ / the proxy class
public class UserServiceProxy implements UserService{

    private UserServiceImpl userService;

    // Use set to inject objects
    public void setUserService(UserServiceImpl userService){
        this.userService = userService;
    }

    @Override
    public void add(a) {
        log("add");
        userService.add();
    }

    @Override
    public void delete(a) {
        log("delete");
        userService.delete();
    }

    @Override
    public void update(a) {
        log("update");
        userService.update();
    }

    @Override
    public void query(a) {
        log("query");
        userService.query();
    }
    // Log method
    public void log(String msg){
        System.out.println("Used"+msg+"Method"); }}Copy the code

4. The customer class

/ / the customer class
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy proxy = newUserServiceProxy(); proxy.setUserService(userService); proxy.add(); }}Copy the code

4.2. Dynamic Proxy

Dynamic proxy: dynamically created using reflection while the program is running

Dynamic proxy classification:

  • Interface-based dynamic proxies (such as InvocationHandler)

    • JDK dynamic proxy
  • Class-based dynamic proxy

    • Additional class
    • Java bytecode implementation:Javasist class library

There are two important classes and interfaces in the Java dynamic proxy mechanismInvocationHandler(Interface) andProxy(class), this class Proxy and interface InvocationHandler are the core of our dynamic Proxy implementation

4.2.1 InvocationHandler interface

  • InvocationHandlerIs the interface implemented by the invocation of the == handler of the proxy proxy instance.

  • Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method call is encoded and dispatched to its invocation handler’sinvokeMethods.

Invoke method details:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
   }
Copy the code

Process method calls on proxy instances and return results. This method is called in the invocation handler when it is invoked on the proxy instance with which it is associated.

parameter

  • Proxy The proxy instance that invokes the method
  • Method The method object of the real method of the object we want to call
  • Args: Refers to parameters passed by proxy object methods

4.2.2, Proxy class

The Proxy class provides static methods for creating dynamic Proxy classes and instances, and is a superclass of all dynamic Proxy classes created by those methods.

It provides many methods, but the one we use most often is the newProxyInstance method.

public static Object newProxyInstance(ClassLoader loader, Class
       [] interfaces, InvocationHandler h)
Copy the code

This method creates a proxy class object that takes three arguments:

  • Loader: A Classloader object that defines which classloader object loads the generated proxy class

  • Interfaces: an array of interface objects that represents the set of interfaces we are going to provide to our proxy objects. If we provide such an array, then we declare that the proxy classes implement these interfaces, and that the proxy classes can call all methods declared in the interface.

  • H: An InvocationHandler object that represents which InvocationHandler object is associated with and ultimately invoked by the dynamic proxy object when it calls a method.

4.2.3 Dynamic proxy implementation

Realization one: rent a house

interface

/ / rent
public interface Rent {
    public void rent(a);
}
Copy the code

True role

// The landlord, the real role of the agent to achieve Rent interface
public class Host implements Rent {
    public void rent(a) {
        System.out.println("The landlord is renting out the house."); }}Copy the code

The invocation handler of the instance that is brokered by proxy

package com.cheng.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// We will use this class to automatically generate the proxy class. This class (ProxyInvocationHandler) is just a call handler for the proxy instance
public class ProxyInvocationHandler implements InvocationHandler {

    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    // Generate the proxy class
    public Object getProxy(a){
      //this.getClass().getClassLoader() represents the loading class rent.getClass().getinterfaces () represents the interface to implement. This represents the current InvocationHandler interface object
      return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
    }
    // Process the proxy instance and return the result
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        seeHose();
        fare();// These two methods are dynamically loaded into the proxy class by reflection
        // The essence of dynamic proxy is reflection
        Object result = method.invoke(rent,args);
        return result;
    }
    public void seeHose(a){
        System.out.println("Agent shows you the house.");
    }
    public void fare(a){
        System.out.println("Collect a broker's fee"); }}Copy the code

The customer class

public class Client {
    public static void main(String[] args) {
        // Real characters
        Host host = new Host();
        // Proxy role, not yet
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        Rent = new Host(); Rent = new Host();
        pih.setRent(host);
        // Dynamically generated proxy classesRent proxy = (Rent) pih.getProxy(); proxy.rent(); }}Copy the code

test

Implementation two: Implement two with the code in dynamic proxy Optimization 4.1 Static proxy

interface

// Abstract the role
public interface UserService {
    public void add(a);
    public void delete(a);
    public void update(a);
    public void query(a);
}
Copy the code

The invocation handler of the proxy instance, which we can encapsulate as a utility class

package com.cheng.demo04;

import com.cheng.demo03.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// We will use this class to automatically generate the proxy class, which is just a handler
public class ProxyInvocationHandler implements InvocationHandler {

    private Object target;

    public void setTarget(Object target) {
        this.target = target;
    }

    // Generate the proxy class
    public Object getProxy(a){
      //this.getClass().getClassLoader() represents the loading class rent.getClass().getinterfaces () represents the interface to implement. This represents the current InvocationHandler interface object
      return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    // Process the proxy instance and return the result
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // The essence of dynamic proxy is reflection
        log(method.getName());// Get the method name dynamically with reflection
        Object result = method.invoke(target,args);
        return result;
    }
    // Add log function
    public void log(String msg){
        System.out.println("[Debug] : Used"+msg+"Method"); }}Copy the code

The customer class

public class Client {
    public static void main(String[] args) {
        // Get the real character
        UserServiceImpl userService = new UserServiceImpl();
        // Get the proxy role, not yet
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        // Handlers handle interface objectspih.setTarget(userService); UserService proxy = (UserService) pih.getProxy(); proxy.add(); }}Copy the code

Advantages of dynamic proxy compared to static proxy:

  • A dynamic proxy class represents an interface, usually a corresponding class of services
  • A dynamic proxy class can proxy multiple classes, as long as the same interface is implemented.

For example, in the example above, any class that implements the UserService interface can be proxied by the dynamic proxy class.

5. Application scenarios of proxy mode

When you cannot or do not want to refer to an object directly or it is difficult to access an object, you can access it indirectly through a proxy object. The proxy pattern is used for two purposes: to protect and enhance target objects.

After analyzing the structure and characteristics of the proxy pattern, let’s look at the following application scenarios.

  • Remote proxy, which is usually used to hide the fact that the target object exists in a different address space to facilitate client access. For example, when a user applies for some web disk space, a virtual disk is created in the user’s file system. When the user accesses the virtual disk, the user accesses the web disk space.
  • Virtual proxy, which is usually used when the target object to be created is expensive. For example, it takes a long time to download a large image, which cannot be completed in a short time due to some complicated calculation. In this case, the real object can be replaced with a small proportion of virtual agents to eliminate the user’s feeling of slow server.
  • Secure proxy, which is often used to control access to real objects by different types of clients.
  • Intelligence guidance, mainly used when calling the target object, with the agent adding some additional processing functions. For example, add the ability to count the number of references to a real object so that when the object is not referenced, it can be released automatically.
  • Lazy loading refers to delaying the loading of a target to improve system performance. Hibernate, for example, has lazy loading of attributes and lazy loading of associated tables.