jdk dynamic proxy and cglb dynamic proxy

Table of contents

overview

JDK dynamic proxy

 cglb dynamic proxy


overview

Both dynamic proxy and static proxy are the implementation of proxy mode, the main difference lies in the timing and method of proxy class generation.

The static proxy is to determine the code of the proxy class at compile time, and the class file of the proxy class already exists before the program runs . The relationship between the proxy class and the delegate class is determined at compile time, so it is called a static proxy. In static proxy, the proxy class needs to implement the same interface as the delegate class or inherit the parent class of the delegate class, so as to be able to perform proxy operations on the delegate class.

A dynamic proxy is a code that generates a proxy class when the program is running, and the proxy class is dynamically generated through a reflection mechanism. The dynamic proxy does not need to implement the same interface as the delegate class or inherit the parent class of the delegate class like the static proxy, it can implement any interface. The advantage of dynamic proxy is that adding a proxy object between the proxy class and the delegate class can control the behavior of the delegate class more flexibly. At the same time, it can also make the code more general and reduce the duplication of code.

Generally speaking, a static proxy can only proxy one delegate class, while a dynamic proxy can proxy multiple delegate classes. However, since the implementation mechanism of the dynamic proxy is relatively complex, the performance overhead of the dynamic proxy is greater than that of the static proxy. Although the static proxy can only proxy one delegate class, it is relatively more efficient because it generates code at compile time.

During the running phase of the program, proxy classes are dynamically generated in memory, which is called dynamic proxy , and the purpose is to reduce the number of proxy classes. Solve the problem of code reuse.

DK dynamic proxy technology: can only proxy interface.

CGLIB dynamic proxy technology: CGLIB (Code Generation Library) is an open source project. It is a powerful, high-performance, high-quality code generation class library, which can extend Java classes and implement Java interfaces at runtime. It can proxy both interfaces and classes , and the bottom layer is realized by inheritance . Performance is better than JDK dynamic proxy. (There is a small and fast bytecode processing framework ASM under the hood.)

JDK dynamic proxy

An interface and an implementing class

Interface class ==> jdk dynamic agent must have an interface class

The full name of the Proxy class: java.lang.reflect.Proxy. This is a class provided by JDK (so called JDK dynamic proxy). It is mainly through this class that the bytecode of the proxy class is generated in memory.

The newProxyInstance() method has three parameters:

  • The first parameter: the class loader. The bytecode is generated in the memory. To execute the bytecode, the bytecode needs to be loaded into the memory first. So specify which class loader to use to load.
  • The second parameter: interface type. The proxy class and the target class implement the same interface, so this parameter is used to tell the JDK which interfaces the dynamic proxy-generated class should implement.
  • The third parameter: call processor. This is an interface specified by the JDK dynamic proxy. The full name of the interface is: java.lang.reflect.InvocationHandler. Obviously this is a callback interface, that is to say, the program to call the method in this interface has been written, and the implementation class of this interface is missing.

The invoke method, which method the user calls the proxy object, is essentially calling
the invoke method of the processor, through which the target method is called, and it also has three parameters:

public Object invoke(Object proxy, Method method, Object[] args)
  1. The first parameter is an instance of the Proxy class type, such as an anonymous $proxy instance
  2. The second parameter is the method object of the delegate class
  3. The third parameter is the method parameter of the delegate class
  4. The return type is the execution result of a method of the delegate class 

orderService

public interface orderService {
    public void order();
}

orderServiceImp

public class orderServiceImp implements  orderService{
    @Override
    public void order() {
        System.out.println("order....");
    }
}

proxyOrderService 

public class proxyOrderService {
    public static void main(String[] args) {
        orderServiceImp orderServiceImp = new orderServiceImp();
        orderService o = (orderService)Proxy.newProxyInstance(orderServiceImp.class.getClassLoader(),
                orderServiceImp.class.getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        orderServiceImp.order();
                        return null;
                    }
                }
        );
        o.order();
    }
}

  

 The code can be encapsulated as follows:

public class proxy implements InvocationHandler {

    private  orderService orderService;

    public proxy(orderService orderService) {
        this.orderService = orderService;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("proxy");
        method.invoke(orderService,args);
        return null;
    }
}
public class proxyOrderService {
    public static void main(String[] args) {
        orderServiceImp orderServiceImp = new orderServiceImp();
        orderService o = (orderService)Proxy.newProxyInstance(orderServiceImp.class.getClassLoader(),
                orderServiceImp.class.getInterfaces(), new proxy(orderServiceImp)
        );
        o.order();
    }
}

 cglb dynamic proxy

CGLIB can proxy both interfaces and classes. The bottom layer is implemented by inheritance. So the proxied target class cannot use final modification.

Similar to the principle of JDK dynamic proxy, what needs to be provided in CGLIB is not InvocationHandler, but: net.sf.cglib.proxy.MethodInterceptor 

To use CGLIB, you need to introduce its dependencies:

<dependency>
  <groupId>cglib</groupId>
  <artifactId>cglib</artifactId>
  <version>3.3.0</version>
</dependency>

Prepare an interface (cglb can use no interface), a class

public interface orderService {
    public void order();
}
public class orderServiceImp implements orderService {
    @Override
    public void order() {
        System.out.println("order....");
    }
}
public class test {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        orderServiceImp orderServiceImp = new orderServiceImp();
        enhancer.setSuperclass(orderServiceImp.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                Object invoke = method.invoke(target, objects);
                return invoke;
            }
        });
        orderServiceImp o =(orderServiceImp)enhancer.create();
        orderServiceImp.order();
    }
}

There is a method intercept() in the MethodInterceptor interface, which has 4 parameters:

The first parameter: proxy object

The second parameter: the target method

The third parameter: the actual parameter when the target method is called

The fourth parameter: proxy method

 For higher versions of JDK, if you use CGLIB, you need to add two startup parameters to the startup item:

  • --add-opens java.base/java.lang=ALL-UNNAMED
  • --add-opens java.base/sun.net.util=ALL-UNNAMED

CGLIB usage steps:

1. Create a bytecode enhancer

2. Set the target audience

3. Set the callback function

4. Create a proxy object

5. Use proxy objects

Guess you like

Origin blog.csdn.net/m0_62436868/article/details/131181725