This is the 21st day of my participation in the August Text Challenge.More challenges in August

1. Proxy mode

What is a proxy module?

For example, if you provide services to others, but you don’t want to be bothered by all kinds of cats and dogs, you find a person to act as your agent instead of having direct access to you. This is the agency model.

In simple terms, proxy objects are used instead of accessing real objects, so that additional functional operations can be provided to extend the functionality of the target object without modifying the original target object.

And there are two kinds of proxy modes:

  1. Static proxy mode: In static proxy, we enhance each method of the target object manually
  2. Dynamic proxy modeDynamic proxies are more flexible than static proxies. Instead of creating a separate proxy class for each target class, and instead of having to implement the interface, we can directly proxy the implementation class (CGLIB dynamic proxy mechanism)


2. Static proxy

In static proxies, every method enhancement we make to the target object is done manually and is very inflexible. There are very few actual application scenarios, and there are almost no static proxy scenarios in daily development. His implementation steps are as follows:

  1. Defines an interface and its implementation class
  2. Create a proxy class that also implements this interface
  3. The proxied class is injected into the proxy class, and the concrete methods are called in the proxy class

Although this does shield the concrete implementation of the proxy class, you can access the specific business logic through the proxy class, but this approach, once the specific implementation to change, then the proxy class and the proxy class have to modify the specific code, very inconvenient


Dynamic proxy

Dynamic proxies are more flexible for dynamic proxies. Instead of creating a separate proxy class for each target class, and instead of having to implement the interface, we can implement the classes directly (through the CGLIB dynamic proxy mechanism).

For Java, there are many ways to achieve dynamic proxy, such as JDK dynamic proxy, CGLB dynamic proxy; There are also many frameworks that rely on dynamic proxy mechanisms, such as Spring AOP, RPC framework; Therefore, learning dynamic proxies is also very helpful in understanding other frameworks


3.1 JDK dynamic proxy mechanism

3.1.1 Implementation steps

  1. Defines an interface and its implementation class
  2. Create another class implementationInvocationHandlerInterface rewriteinvokeMethods,invokeMethod we call native methods (methods of the propped class) and customize some processing logic.
  3. throughProxy.newProxyInstance(ClassLoader loader,Class<? >[] interfaces,InvocationHandler h)Method to create a proxy object

Let’s demonstrate this in code:

Step 1: Define an interface and its implementation class, an implementation class

Define an interface for sending messages:

public interface MsgService {
    String send(String message);
}
Copy the code
public class MsgServiceImpl implements MsgService {
    @Override
    public String send(String message) {
        System.out.println("Sent a message.");
        returnmessage; }}Copy the code


Step 2: Create a class that implements the InvocationHandler interface and rewrite the Invoke method, where we invoke the proxied class’s method

Dynamic proxy class:

public class MsgInvocationHandler implements InvocationHandler {

    /** The proxied real object */
    Object target;

    public MsgInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target, args);
        returnresult; }}Copy the code


Step three: Actual use

public static void main(String[] args) {
    MsgService msgService = (MsgService) Proxy.newProxyInstance(
            MsgServiceImpl.class.getClassLoader(),
            MsgServiceImpl.class.getInterfaces(),
            new MsgInvocationHandler(new MsgServiceImpl()));

    msgService.send("What are you worried about?");
}
Copy the code

Running results:

A message was sentCopy the code


3.1.2 summary

  1. As you can see, in the JDK dynamic proxy implementation, mainly throughProxy.newProxyInstance()Method to dynamically produce proxy objects
  2. throughProxy.newProxyInstance()The created proxy object actually calls the implementation when the method is calledInvocationHandlerClass of the interfaceinvoke()methods

The JDK dynamic proxy has its own problem, that is, it can only proxy classes that implement the interface. To solve this problem, CGLIB dynamic proxy was developed


3.2 GLIB dynamic Proxy mechanism

3.2.1 Implementation Procedure

  1. Define a class
  2. The customMethodInterceptorPay equal attention to writingintercept()Method,intercept()Methods used to intercept enhanced propped classes, and in JDK dynamic proxiesinvoke()Methods are similar;
  3. throughEnhancerOf the classcreate()Create a proxy class;

Here’s a code example:

Step 1: Introduce dependencies

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.3.0</version>
</dependency>
Copy the code

Step 2: Define a class that needs to be proxied

public class MsgService {
    public String send(String message) {
        System.out.println("Sent a message.");
        returnmessage; }}Copy the code

Step 3: Use MethodInterceptor

public class MsgMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result = methodProxy.invokeSuper(o, objects);
        returnresult; }}Copy the code

Step 4: Actual use:

public static void main(String[] args) {
    Class clazz = MsgService.class;
    // Create dynamic proxy enhancement classes
    Enhancer enhancer = new Enhancer();
    // Set the class loader
    enhancer.setClassLoader(clazz.getClassLoader());
    // Set the proxied class
    enhancer.setSuperclass(clazz);
    // Set method interceptor
    enhancer.setCallback(new MsgMethodInterceptor());
    // Create the proxy class
    MsgService msgService = (MsgService) enhancer.create();

    msgService.send("What are you looking at?");
}
Copy the code

Program output:

A message was sentCopy the code


3.2.2 summary

  1. CGLIB dynamic proxy mechanismMethodInterceptorThe interface andEnhancerClass is the core
  2. You need to customizeMethodInterceptorPay equal attention to writinginterceptMethod,interceptMethods used to intercept enhanced proxied classes
  3. throughEnhancerClass to dynamically retrieve the proxied class. When the proxied class calls a method, what is actually called isMethodInterceptorIn theinterceptmethods


4. Difference between dynamic proxy and static proxy

  1. Flexibility: Dynamic proxies are more flexible in that they don’t have to implement interfaces, they can implement classes directly, and they don’t need to create a proxy class for each target class. In addition, in static proxies, once the interface adds new methods, both the target object and the proxy object need to be modified, which can be very cumbersome
  2. JVM level: Static agents convert interfaces, implementation classes, and proxy classes into actual class files at compile time. Dynamic proxies, on the other hand, generate bytecodes dynamically at run time and load them into the JVM