Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

  • 23 design modes for shorthand
  • The singleton pattern
  • Factory Method pattern
  • Abstract Factory pattern
  • The Builder/Builder pattern
  • Prototype mode
  • Flyweight mode
  • The facade pattern
  • Adapter mode
  • Decorator pattern
  • Observer mode
  • Strategy mode
  • Bridge mode
  • The Template Method pattern
  • The Chain of Responsibility model
  • Composite mode
  • Updates continue at……

Here are 23 design patterns to memorize quicklyThe proxy patternRelated content.

The schema definition

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 structure of the proxy pattern is relatively simple, mainly by defining a proxy inheriting the abstract topic to contain the real topic, so as to achieve access to the real topic.

In code, proxies are generally understood as code enhancement, which essentially means adding some code logic before and after the original code logic without the caller being aware of it.

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

  • Static: 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: dynamically created using reflection while the program is running

Problem solved

Problems with accessing objects directly, such as objects that are accessed on remote machines. 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.

Patterns of

To compose (a role). role
Abstract the Subject class Declare real topics and business methods implemented by proxy objects through interfaces or abstract classes.
The Real Subject class The concrete business that implements the abstract topic is the real object represented by the proxy object, and is the object that is ultimately referenced.
Proxy class Provides the same interface as the real topic, with internal references to the real topic, which can access, control, or extend the functionality of the real topic.

Static agent

Using the step

Step 1: Define the abstract topic class

// Abstract theme
interface Subject {
    void request(a);
}
Copy the code

Step 2: Define the real topic class

// True theme
class RealSubject implements Subject {
    public void request(a) {
        System.out.println("Access real topic methods..."); }}Copy the code

Step 3: Define the proxy class

/ / agent
class Proxy implements Subject {
    private RealSubject realSubject;

    public void request(a) {
        if (realSubject == null) {
            realSubject = new RealSubject();
        }
        preRequest();
        realSubject.request();
        postRequest();
    }

    public void preRequest(a) {
        System.out.println("Pre-processing before accessing the real subject.");
    }

    public void postRequest(a) {
        System.out.println("Follow-up after accessing the real topic."); }}Copy the code

Step 4: Test

public class ProxyPattern {

    public static void main(String[] args) {
        Proxy proxy = newProxy(); proxy.request(); }}Copy the code

The following output is displayed:

Preprocessing before accessing the real topic. Access real topic methods... Follow-up after accessing the real topic.Copy the code

As you can see, the Subject interface is Subject, the RealSubject is RealSubject implements the Subject interface, and the Proxy class is Proxy. The method of the Proxy class implements the Subject class, and the operations before and after the Proxy are written in the code. This is the simple implementation of static Proxy. You can see that the advantages and disadvantages of implementing static proxies are obvious.

Advantages of static proxy

It makes the business dealt with by the real topic more pure, and no longer pays attention to some public things. The public business is completed by the agent to realize the division of business, and the public business becomes more centralized and convenient when it expands.

Disadvantages of static proxy

This approach is straightforward and simple, but the downside is that the proxy class must be written in advance, and if the topic interface changes, the code for the proxy class also changes, which is costly to maintain.

Is there a way to compensate for the disadvantages of static proxies? Dynamic proxies can be used without having to write a proxy method for each interface.

A dynamic proxy

Dynamic proxy, in Java code dynamic proxy classes use bytecode dynamic generation load technology to generate load classes at run time.

There are many ways to generate dynamic proxy classes, such as dynamic processing in the JDK, CGLIB, Javassist, and ASM libraries.

  • The JDK’s dynamic proxy is simple to use and built into the JDK, so there is no need to import third-party Jar packages, but it is relatively weak.
  • Both CGLIB and Javassist are advanced bytecode generation libraries with overall better performance than the dynamic proxies that come with the JDK and are very powerful.
  • ASM is a low-level bytecode generation tool. Using ASM is almost like programming with Java Bytecode, which is the most demanding for developers and, of course, the most high-performance dynamic proxy generation tool. However, THE use of ASM is tedious, and the performance is not an order of magnitude of improvement, compared with CGLIB and other advanced bytecode generation tools, ASM program maintenance is poor, if not in the performance of the situation is demanding, CGLIB or Javassist is recommended.

Here we introduce two dynamic proxy technologies that are very common and often used in interviews: dynamic processing in the JDK and CGLIB.

JDK dynamic proxy

Java provides a Proxy class. The newInstance method of Proxy class can be used to generate a Proxy object of an object. This method takes three parameters:

  1. Class loader [Usually we use the loader of the proxyed class]
  2. Specify the interface of the class to be proxied
  3. Methods in the proxy object to do what

Using the step

Step 1: Define the abstract topic class

// Abstract theme
interface Subject {
    void request(a);
}
Copy the code

Step 2: Define the real topic class

// True theme
class RealSubject implements Subject {
    public void request(a) {
        System.out.println("Access real topic methods..."); }}Copy the code

Step 3: Use proxy. newProxyInstance to generate the Proxy object

class ProxyHandler implements InvocationHandler {

    private Subject subject; // Define the topic interface

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // If this is the first call, generate the real theme
        if (subject == null) {
            subject = new RealSubject();
        }

        if ("request".equalsIgnoreCase(method.getName())) {
            System.out.println("Pre-processing before accessing the real subject.");
            Object result = method.invoke(subject, args);
            System.out.println("Follow-up after accessing the real topic.");
            return result;
        } else {
            // If the request method is not called, return the real topic to do the actual operation
            returnmethod.invoke(subject, args); }}// Use proxy.newProxyInstance to generate a Proxy object
    static Subject createProxy(a) {
        Subject proxy = (Subject) Proxy.newProxyInstance(
                ClassLoader.getSystemClassLoader(), // The class loader for the current class
                new Class[]{Subject.class}, // The proxied topic interface
                new ProxyHandler() // Proxy object, here is the current object
        );
        returnproxy; }}Copy the code

Step 4: Test the output

public class ProxyPattern {
    public static void main(String[] args) { Subject subject = ProxyHandler.createProxy(); subject.request(); }}Copy the code

The following output is displayed:

Preprocessing before accessing the real topic. Access real topic methods... Follow-up after accessing the real topic.Copy the code

Starting with Debug, you can see that methods are implemented in the proxy class. You can do a lot of things before and after executing methods on real topics in the proxy class.

Although this approach seems to be convenient, the careful students should also have observed that JDK dynamic proxy technology implementation must be an interface, so the advantages and disadvantages of JDK dynamic proxy are very obvious

JDK dynamic proxy benefits

  • No need to write a formally identical wrapper class for the real topic, reducing maintenance costs;
  • The execution logic of the agent class can be formulated at run time to improve the flexibility of the system.

Disadvantages of JDK dynamic proxies

  • JDK dynamic proxy,The real themeThe best that must be achievedTheme interfaceIf theThe real theme** does not implement **The main figure interfaceOr notTheme interface, cannot be generatedProxy object **.

Since you must have an interface to use the JDK’s dynamic proxy, is there a way to use dynamic proxies without an interface and with only real topic implementation classes? This is the second type of dynamic proxy: CGLIB;

CGLIB dynamic proxy

To generate a dynamic proxy using CGLIB, you first need to generate an instance of the Enhancer class and specify the callback class to handle the proxy business. In Enhancer. The create () method, using DefaultGeneratorStrategy. The Generate () method to Generate dynamic proxy class bytecode, and stored in a byte array. Then use reflectutils.defineclass () method and call classLoader.defineclass () method through reflection to load the bytecode into ClassLoader and complete the class loading. Finally, reflectutils.newinstance () is used to generate and return an instance of the dynamic class through reflection. The basic flow is to generate Class bytecode from a specified callback Class — bytecode is defined as a Class via defineClass() — and generate instances of that Class using a reflection mechanism.

Using the step

Step 1: Define the real topic

class WorkImpl {

    void addWorkExperience(a) {
        System.out.println("Common ways to gain work experience..."); }}Copy the code

Step 2: Create the proxy class

class WorkImplProxyLib implements MethodInterceptor {

    // Create a proxy object
    Object getWorkProxyImplInstance(a) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(WorkImpl.class);
        // Callback method
        enhancer.setCallback(this);
        // Create a proxy object
        return enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Start...");
        methodProxy.invokeSuper(obj, args);
        System.out.println("End...");
        return null; }}Copy the code

Step 3: Test the output

public class CglibProxy {

    public static void main(String[] args) {
        WorkImplProxyLib cglib = newWorkImplProxyLib(); WorkImpl workCglib = (WorkImpl) cglib.getWorkProxyImplInstance(); workCglib.addWorkExperience(); }}Copy the code

The following output is displayed:

Began to... Common ways to gain work experience... The end...Copy the code

CGLIB dynamic proxy advantages

CGLIB inherits proxies regardless of whether the target object implements the interface, which compensates for the JDK’s dynamic proxies.

Disadvantages of CGLIB dynamic proxy

  1. Dynamic proxy objects created by CGLib perform much better than those created by JDK. However, CGLib takes much longer to create proxy objects than the JDK, so for singleton objects, CGLib works better than JDK because you don’t need to create objects frequently.
  2. Because CGLib is subclassed dynamically, there is no proxy for final methods.

Application scenarios

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.

The proxy pattern has several applications, as described below:

  1. Remote proxies, which provide a local representation of an object in different address Spaces, hide the fact that an object exists in different address Spaces. For example, if you add a Web reference to a WebService to your application project, you’ll claim a WebReference folder and some files in your project. This allows that client program to call the proxy to solve the remote access problem;
  2. Virtual proxies are expensive objects created on demand to hold real objects that take a long time to instantiate. So that you can reach the optimization of performance, such as open a web page, this page contains a large number of words and images, but we can quickly see the text, but the picture is to download one by one to see that those who do not open the picture box, is through the virtual generation to replace the real image, the agent stores the path and the size of the real image;
  3. A secure proxy that controls access to real objects. Generally used when objects should have different access permissions;
  4. A pointer reference means that the proxy handles something else when the real object is called. Such as counting the number of references to a real object so that it can be freed automatically when it is not referenced, or loading a persistent object into memory when it is first referenced, or checking to see if it has been freed before accessing an actual object to ensure that it cannot be changed by other objects. These are all done by attaching some housekeeping to accessing an object through a proxy;
  5. Lazy loading, a classic application of proxy mode to achieve lazy loading is in Hibernate framework. When Hibernate loads entity beans, it does not load all of the database’s data at once. By default, it uses lazy loading to improve system performance. Lazy loading in Hibernate can be divided into two categories: lazy loading of attributes and lazy loading of associated tables. The implementation principle is to use proxies to intercept original getter methods and load actual data from the database or other third-party components only when object data is actually used, thus improving system performance.

Other proxy modes

  • Firewall proxy: The Intranet accesses the public network through the proxy.
  • Caching proxy: for example, when we request image file resources, we first go to the caching proxy. If we cannot get the resources, we go to the public network or the database, and then cache.
  • Remote proxy: a local representation of a remote object through which it can be called. Remote agents communicate with real remote objects over the network.
  • Synchronization agent: mainly used in multi-threaded programming, to complete the synchronization between multiple threads.

PS: The above code is submitted to Github: github.com/Niuh-Study/…

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy