CGLIB dynamic proxy and JDK dynamic proxy

This article is from the Huawei cloud community “learn about the JDK dynamic proxy and CGLIB dynamic proxy” by Code.

What’s the difference between the two

Jdk dynamic proxy: Use the interceptor (must implement the InvocationHandler interface) and reflection mechanism to generate a proxy interface anonymous class, before calling the specific method to call the InvokeHandler to handle

2, Cglib dynamic proxy: using the ASM framework, load the class file generated by the proxy object class, and modify its bytecode generation subclass to proxy

So:

If you want to implement JDK dynamic proxies, the proxy class must implement the interface, otherwise it cannot be used;

If you want to use a CGlib dynamic proxy, the proxy class cannot use final modifier classes and methods;

There are: In jdk6 has, jdk7, jdk8 gradually the JDK dynamic proxy after optimization, the call number is less, the JDK efficiency is higher than the additional agency efficiency, only when a large number of calls, jdk6 has and jdk7 than additional agent efficiency is lower, but by jdk8, The JDK agent is more efficient than the CGLIB agent.

How to implement

JDK dynamic proxy

UserService interface

public interface UserService {

    void addUser();

    void updateUser(String str);

}
Copy the code

UserServiceImpl implementation class

Public class UserServiceImpl implements UserService {@override public void addUser() {system.out.println (" addUser "); } @override public void updateUser(String STR) {system.out.println (" updateUser "+ STR); }}Copy the code

The UserProxy proxy class implements the InvocationHandler interface to override the Invoke method

public class UserProxy implements InvocationHandler {
    private Object target;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object res = method.invoke(target, args);

        System.out.println("记录日志");

        return res;
    }
}
Copy the code

The test test class

public class test { public static void main(String[] args) { UserServiceImpl impl = new UserServiceImpl(); UserProxy userProxy = new UserProxy(impl); UserService userService = (UserService) Proxy.newProxyInstance(impl.getClass().getClassLoader(),impl.getClass().getInterfaces(),userProxy); userService.addUser(); Userservice.updateuser (" : I am a shrimp "); }}Copy the code

Visibility is enhanced to print out logging

CGlib dynamic proxy

Unlike JDK dynamic proxies, CGlib requires importing Jar packages, so I used SpringBoot to import the dependencies directly

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

UserServiceImpl Proxied class

Public class UserServiceImpl {public void addUser() {system.out.println (" add a user "); } public void deleteUser() {system.out.println (" deleteUser "); }}Copy the code

UserServiceCGlib agent

public class UserServiceCGlib implements MethodInterceptor { private Object target; public UserServiceCGlib() { } public UserServiceCGlib(Object target) { this.target = target; } public Object getProxyInstance() {//1. Create a utility class Enhancer Enhancer = new Enhancer(); SetSuperclass (target.getClass())); //3. Set the callback function enhancer.setCallback(this); Return enhancer. Create (); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy MethodProxy) throws Throwable {system.out.println (" enhancement start ~~~"); Object result = methodProxy.invokeSuper(o, objects); System.out.println(" enhanced end ~~~"); return result; }}Copy the code

The test test class

public class test { public static void main(String[] args) { UserServiceCGlib serviceCGlib = new UserServiceCGlib(new UserServiceImpl()); UserServiceImpl userService = (UserServiceImpl)serviceCGlib.getProxyInstance(); userService.addUser(); System.out.println(); userService.deleteUser(); }}Copy the code

Visibility is enhanced to print out logging

Usage scenarios

Here I believe that you have basically mastered the difference and implementation of JDK dynamic proxy and CGlib dynamic proxy

However, in the interview process, in addition to the above points, you also need to answer how they are used, which is actually a plus

So, what are the usage scenarios of these two dynamic proxies??

Spring AOP

Here is how Spring AOP creates a proxy

@Override public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<? > targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } / / if the if (targetClass isInterface () | | Proxy. IsProxyClass (targetClass)) {return new JdkDynamicAopProxy (config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); }}Copy the code

If the target object implements the interface, the JDK’s dynamic proxy is used by default

If the target object implements the interface, you can force the use of CGLIB3. If the target object does not implement the interface, you must use the CGLIB library. Spring will automatically convert the JDK dynamic proxy to CGLIB

If you want to force CGLIB to implement AOP, you need to configure spring.aop.proxy-target-class=true or @enableAspectJAutoProxy (proxyTargetClass= true)

Click to follow, the first time to learn about Huawei cloud fresh technology ~