JDK dynamic proxy and cglib bytecode enhancement

1、 JDK dynamic agent

Java in Java Lang.reflect package has its own proxy support. This class (proxy. Java) is used to dynamically generate proxy classes. Just pass in the target interface, the class loader of the target interface and invocationhandler to generate proxy classes and proxy objects for the target interface. We call this Java technology: dynamic proxy

@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    throws IllegalArgumentException
{
//...
}

In Java, if you want to generate a proxy object of an object, the object must have an interface, so interfaces must be an interface.

In dynamic proxy technology, no matter what method the user calls the proxy object, it calls the invoke method of the invocationhandler written by the developer (this is equivalent to that the invoke method intercepts the method call of the proxy object).

Therefore, the overall process of JDK dynamic agent is as follows:

The following is a specific example of implementing AOP with JDK dynamic code:

1. Target class

public interface UserService {
    void eat();
}
public class UserServiceImpl implements UserService {
    @Override
    public void eat() {
        System.out.println("吃东西");
    }
}

2. Aspect class

public class MyAspect {
    /**
     * 前置通知
     */
    public void before() {
        System.out.print("先洗手再");
    }
}

3. Weaving process

/**
 * 产生代理对象的工厂类
 */
public class Myfactorybean {

    private Myfactorybean() {
    }
    
    public static UserService getInstance() {
        // target : 目标类
        final UserService userService = new UserServiceImpl();
        // Aspect : 切面类
        final MyAspect myAspect = new MyAspect();
        // Weaving : 织入,也就是产生代理的过程
        UserService proxyInstance = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(),new Class[]{UserService.class},(Object proxy,Method method,Object[] args) -> {
                    // 模拟切点 - pointcut
                    if ("eat".equals(method.getName())) {
                        myAspect.before();
                    }
                    return method.invoke(userService,args);
                });
        return proxyInstance;
    }
}
    public static void main(String[] args) {
        UserService userService = Myfactorybean.getInstance();
        // 先洗手再吃东西
        userService.eat();
    }

Think about it. This is actually very similar to the AOP we usually use. Spring defines pre notification (@ before), exception notification (@ afterthrowing) and so on. Spring just filters these annotations to choose when to call the notification method. In addition, spring also selects the target class and pointcut through pointcut expression.

2、 Cglib dynamic proxy

Cglib dynamic proxy needs to introduce a third-party library. It implements call interception by modifying the proxy object to generate subclasses. The proxy object does not need to implement an interface, but the proxy class cannot be final and the proxy method cannot be final.

/**
 * 产生代理对象的工厂类
 */
public class Myfactorybean {

    private Myfactorybean() {
    }

    public static UserService getInstance() {
        // target : 目标类
        final UserService userService = new UserServiceImpl();
        // Aspect : 切面类
        final MyAspect myAspect = new MyAspect();
        // Weaving : 织入,也就是产生代理的过程
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(userService.getClass());
        enhancer.setUseCache(false);
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object o,Object[] objects,MethodProxy methodProxy) throws Throwable {
                // 模拟 pointcut-切点
                if ("eat".equals(method.getName())) {
                    myAspect.before();
                }
                return methodProxy.invokeSuper(o,objects);
            }
        });
        return (UserService) enhancer.create();
    }

    public static void main(String[] args) {
        UserService proxyInstance = Myfactorybean.getInstance();
        // 先洗手再吃东西
        proxyInstance.eat();
    }
}

3、 Summary

When implementing dynamic proxy in JDK, the proxy class must be an interface or a class that inherits the interface, Because the proxy class finally generated by JDK actually implements the interface represented by the proxy class and inherits the proxy class in Java (inheriting the proxy class is to judge whether the class is a proxy class). Find the method of the interface through reflection and call the invoke method of invocationhandler to intercept.

Cglib bytecode enhancement is a good supplement to JDK dynamic proxy. The proxy class finally generated in cglib inherits the class represented by the proxy class, and implements the proxy by rewriting the non final method in the proxy class.

The summary is as follows:

If we do not impose restrictions on the proxy means used in spring's AOP, we will treat them differently according to whether the class has an interface:

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>