Writing in the front

  • Take notes on learning design patterns
  • Improve flexibility in the use of design patterns

Learning to address

https://www.bilibili.com/vide…

https://www.bilibili.com/vide…

Refer to the article

http://c.biancheng.net/view/1…

** Project source https://gitee.com/zhuang-kang/DesignPattern**

17. Proxy mode

17.1 Definition and characteristics of the proxy schema

Definition of a proxy pattern: For some reason an object needs to be provided with a proxy to control access to that object. In this case, the access object is not suitable or cannot directly refer to the target object, and the proxy object acts as an intermediary between the access object and the target object.

The main advantages of the proxy pattern are:

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

Its main disadvantages are:

  • The proxy pattern causes an increase in 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;

17.2 Structure and implementation of the proxy pattern

17.2.1 Structure of the proxy pattern

  1. Abstract Subject classes: Declare business methods implemented by real subjects and proxy objects through interfaces or abstract classes.
  2. Real Subject class: Implements a concrete business in an abstract Subject, is the Real object that the proxy object represents, and is the object that is ultimately referenced.
  3. Proxy class: Provides the same interface as the real topic, with internal references to the real topic, and it can access, control, or extend the functionality of the real topic.

Depending on the creation period of the agent, the proxy pattern is divided into static and dynamic.

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

17.2.2 Code Implementation

Relationship between the class diagram

17.2.2.1Static agent

SellTickets

package com.zhuang.proxy.static_proxy; /** * @ClassName sellTickets * @Description * @Date 2021/3/26 8:01 * @Created by Dell */ public interface SellTickets { void sell(); }

Transition

package com.zhuang.proxy.static_proxy;

/**
 * @Classname Transition
 * @Description 火车站,具有卖票功能,实现接口
 * @Date 2021/3/26 8:01
 * @Created by dell
 */

public class Transition implements SellTickets {
    @Override
    public void sell() {
        System.out.println("火车站卖票");
    }
}

ProxyPoint

package com.zhuang.proxy.static_proxy; /** * @className proxyPoint * @description outlets * @date 2021/3/26 8:02 * @Created by Dell */ public class proxyPoint  implements SellTickets { private Transition transition = new Transition(); Public void Sell () {System.out.println(" outlets charges a service charge "); transition.sell(); }}

Client

package com.zhuang.proxy.static_proxy; /** * @ClassName Client * @Description * @Date 2021/3/26 8:02 * @Created by Dell */ public class Client { public static void main(String[] args) { ProxyPoint proxyPoint = new ProxyPoint(); proxyPoint.sell(); }}

As you can see from the above code, the test class accesses objects of the ProxyPoint class directly. In other words, ProxyPoint acts as an intermediary between the access object and the target object. Enhancements have also been made to the Sell method

17.2.2.2 JDK dynamic proxy

Using dynamic proxies to implement the above example, let’s start with the dynamic proxies provided by the JDK. Java provides a dynamic Proxy class, Proxy. Proxy is not a class of the Proxy object we mentioned above, but provides a static method to create the Proxy object (newProxyInstance method) to get the Proxy object.

SellTickets

package com.zhuang.proxy.jdk_proxy; /** * @ClassName sellTickets * @Description * @Date 2021/3/26 8:01 * @Created by Dell */ public interface SellTickets { void sell(); }

Transition

package com.zhuang.proxy.jdk_proxy;

/**
 * @Classname Transition
 * @Description 火车站,具有卖票功能,实现接口
 * @Date 2021/3/26 8:01
 * @Created by dell
 */

public class Transition implements SellTickets {
    @Override
    public void sell() {
        System.out.println("火车站卖票");
    }
}

ProxyFactory

package com.zhuang.proxy.jdk_proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @ClassName ProxyFactory * @Description * @Date 2021/3/26 8:11 * @Created by Dell */ public class ProxyFactory { private Transition transition = new Transition(); Public sellTickets getProxyObject() {/* newProxyInstance ClassLoader, Class<? >[] interfaces, The invocation method of the Proxy proxy object corresponds to the actual parameter */ passed by the Args proxy object when the method instance of the interface method invoked by the proxy object calls the interface method SellTickets sellTickets = (SellTickets) Proxy.newProxyInstance(transition.getClass().getClassLoader(), transition.getClass().getInterfaces() , new InvocationHandler() { @Override public Object invoke(Object proxy, Throws Throwable {System.out.println() throws Throwable {System.out.println(); Object result = Method. invoke(transition, args); return result; }}); return sellTickets; }}

Client

package com.zhuang.proxy.jdk_proxy; /** * @ClassName Client * @Description * @Date 2021/3/26 8:20 * @Created by Dell */ public class Client { Public static void main(String[] args) {proxyFactory Factory = new ProxyFactory(); SellTickets proxyObject = factory.getProxyObject(); proxyObject.sell(); }}

Using dynamic proxies, we consider the following questions:

  • Is ProxyFactory a proxy class?

    ProxyFactory is not a proxy class as described in the proxy pattern, but a proxy class is a class that is dynamically generated in memory during the execution of a program. To view the structure of the proxy class through Alibaba’s open source Java diagnostic tool (Arthas [Alsace]) :

    package com.sun.proxy; import com.itheima.proxy.dynamic.jdk.SellTickets; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class $Proxy0 extends Proxy implements SellTickets { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler invocationHandler) { super(invocationHandler); } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("com.itheima.proxy.dynamic.jdk.SellTickets").getMethod("sell", new Class[0]); m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]); return; } catch (NoSuchMethodException noSuchMethodException) { throw new NoSuchMethodError(noSuchMethodException.getMessage());  } catch (ClassNotFoundException classNotFoundException) { throw new NoClassDefFoundError(classNotFoundException.getMessage()); } } public final boolean equals(Object object) { try { return (Boolean)this.h.invoke(this, m1, new Object[]{object}); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final String toString() { try { return (String)this.h.invoke(this, m2, null); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final int hashCode() { try { return (Integer)this.h.invoke(this, m0, null); } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); } } public final void sell() { try { this.h.invoke(this, m3, null); return; } catch (Error | RuntimeException throwable) { throw throwable; } catch (Throwable throwable) { throw new UndeclaredThrowableException(throwable); }}}

From the above class, we can see the following information:

  • The proxy class ($Proxy0) implements sellTickets. This confirms our previous statement that the real class implements the same interface as the proxy class.
  • The proxy class ($Proxy0) passes the anonymous inner class object we provided to the parent class.
  • What is the execution flow of dynamic proxies?

    Here are the highlights:

    Public final class $Proxy0 extends Proxy implements sellTickets {private static Method m3; public $Proxy0(InvocationHandler invocationHandler) { super(invocationHandler); } static { m3 = Class.forName("com.itheima.proxy.dynamic.jdk.SellTickets").getMethod("sell", new Class[0]); } public final void sell() { this.h.invoke(this, m3, null); }} public class Proxy implements java.io.Serializable {protected InvocationHandler h; public class Proxy implements java.io.Serializable; protected Proxy(InvocationHandler h) { this.h = h; }} public class ProxyFactory {private TrainStation = new TrainStation(); public SellTickets getProxyObject() { SellTickets sellTickets = (SellTickets) Proxy.newProxyInstance(station.getClass().getClassLoader(), station.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println(); Object result = method.invoke(station, args); return result; }}); return sellTickets; Public class Client {public static void main(String[] args) {proxyFactory Factory = new ProxyFactory(); SellTickets proxyObject = factory.getProxyObject(); proxyObject.sell(); }}

The execution process is as follows:

  1. The Sell () method is called from the proxy object in the test class
  2. By the nature of polymorphism, it is the sell() method in the proxy class ($Proxy0) that is executed
  3. The invoke method of the child implementation class object of the InvocationHandler interface is called in the Sell () method of the proxy class ($Proxy0)
  4. The invoke method executes the sell() method in the class of the real object (TrainStation) through reflection

17.2.2.3 CGLB agent

TrainStation

package com.zhuang.proxy.cglib_proxy; /** * @className TrainStation * @description TrainStation * @date 2021/3/26 8:31 * @Created by Dell */ public class TrainStation {public void Sell () {System.out.println(); }}

ProxyFactory

package com.zhuang.proxy.cglib_proxy; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; /** * @ClassName ProxyFactory * @Description ProxyFactory implements MethodInterceptor * @Date 2021/3/26 8:32 * @Created by Dell */ public class ProxyFactory implements MethodInterceptor { private TrainStation target = new TrainStation(); Public trainStation getProxyObject() {public trainStation getProxyObject() {public trainStation getProxyObject() { // Set the superclass bytecode object enhancer.setSuperClass (target.getClass()); // Set the callback function enhancer.setcallback (this); // create the agent object TrainStation obj = (TrainStation) enhancer.create(); return obj; } @Override public Object intercept(Object o, Method method, Object[] args, Throws Throwable {System.out.println(); throws Throwable {System.out.println(); Object result = methodProxy.invokeSuper(o, args); return result; }}

Client

package com.zhuang.proxy.cglib_proxy;

/**
 * @Classname Client
 * @Description CGLIB动态代理模式 测试类
 * @Date 2021/3/26 8:42
 * @Created by dell
 */

public class Client {
    public static void main(String[] args) {
        //创建代理工厂对象
        ProxyFactory factory = new ProxyFactory();
        //获取代理对象
        TrainStation proxyObject = factory.getProxyObject();

        proxyObject.sell();
    }
}

17.2.3 Comparison of the three agents

  • JDK and CGlib proxies

    CGLIB is used to realize dynamic proxy. The underlying CGLIB adopts ASM bytecode generation framework and uses bytecode technology to generate proxy classes. Before JDK1.6, the reflection efficiency is higher than using Java. The only caveat is that CGLIB cannot proxies a class or method that is declared final, because CGLIB works by dynamically subclassing the proxered class.

    After JDK1.6, JDK1.7, and JDK1.8 are gradually optimized for the JDK dynamic proxy, the efficiency of the JDK proxy is higher than that of the CGLib proxy in the case of fewer calls. JDK1.6 and JDK1.7 are slightly lower than that of the CGLib proxy only when a large number of calls are made. The JDK proxy is more efficient than the CGlib proxy. So if there is an interface to use the JDK dynamic proxy, if there is no interface to use the CGLIB proxy.

  • Dynamic and static proxies

    The main advantage of dynamic proxies over static proxies is that all methods declared in the interface are transferred to a centralized method in the InvocationHandler (InvocationHandler. Invoke). In this way, when there are a large number of interface methods, we can handle them flexibly without having to transit each method like static proxies.

    If the interface adds a method, the static proxy pattern requires all proxy classes to implement that method in addition to all implementation classes. Increases the complexity of code maintenance. Dynamic proxies do not have this problem

17.3 Application Scenarios of Proxy Mode

  • Remote agent

    The local service requests the remote service over the network. In order to achieve local to remote communication, we need to implement network communication, to deal with the possible exceptions. For good code design and maintainability, we hide the network communication part and expose the local service to an interface through which you can access the functionality provided by the remote service without worrying too much about the details of the communication part.

  • Firewall agent

    When you configure your browser to use proxies, the firewall forwards your browser’s requests to the Internet; When the Internet returns the response, the proxy server forwards it to your browser.

  • Protect or Access agent

    Control access to an object, providing different levels of access to different users if needed.

Write in the last

  • If my article is useful to you, please click 👍, thank you!
  • Let me know in the comments section if you have any questions! 💪