Talking about the difference between Spring's two proxies JDK and CGLIB

First, the principle difference:

Java dynamic proxy uses the reflection mechanism to generate an anonymous class that implements the proxy interface, and calls InvokeHandler to process it before calling the specific method.

The cglib dynamic proxy uses the asm open source package, loads the class file of the proxy object class, and generates subclasses by modifying its bytecode.

1. If the target object implements the interface, the dynamic proxy of the JDK will be used to implement AOP by default. 
2. If the target object implements the interface, you can force the use of CGLIB to implement AOP. 

3. If the target object does not implement the interface, the CGLIB library must be used, and spring will automatically convert between the JDK dynamic proxy and CGLIB

How to force AOP to be implemented using CGLIB?
 (1) Add CGLIB library, SPRING_HOME/cglib/*.jar (2) Add <aop:aspectj-autoproxy proxy-target-class="true"/> JDK dynamic proxy and CGLIB bytecode to
 the spring configuration file

the difference?
 (1) JDK dynamic proxy can only generate proxy for the class that implements the interface, but not for the class
 (2) CGLIB implements the proxy for the class, mainly to generate a subclass for the specified class, and override the method
   because it is inheritance, So it is best not to declare the class or method as final 

Second, the code implementation

package com.fy.spring.proxy;    
    
public interface UserManager {    
    public void addUser(String id, String password);    
    public void delUser(String id);    
}   
package com.fy.spring.proxy;    
    
public class UserManagerImpl implements UserManager {    
    
    public void addUser(String id, String password) {    
        System.out.println( ".: UserManagerImpl.addUser() method is used! " );    
    
    }    
    
    public void delUser(String id) {    
        System.out.println( ".: UserManagerImpl.delUser() method is used! " );    
    
    }    
}  

JDK dynamic proxy class

package com.fy.spring.proxy;    
import java.lang.reflect.InvocationHandler;    
import java.lang.reflect.Method;    
import java.lang.reflect.Proxy;    
/**   
 *    
 * JDK dynamic proxy class   
 *    
 *   
 */    
public class JDKProxy implements InvocationHandler {    
    
    private Object targetObject; // The target object that needs to be proxied    
    
    public Object newProxy(Object targetObject) { // Pass in the target object for proxying     
        this .targetObject = targetObject;     
         return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),    
                targetObject.getClass().getInterfaces(), this ); // return the proxy object     
    }    
    
    public Object invoke(Object proxy, Method method, Object[] args)//invoke方法    
            throws Throwable {    
        checkPopedom(); // Generally, we perform logical processing functions, such as this place is to simulate the check permission     
        Object ret = null ;       // Set the return value of the method     
        ret = method.invoke(targetObject, args);        // Call the invoke method, ret Store the return value of the method     
        return ret;    
    }    
    
    private  void checkPopedom() { // Example of simulating checking permission     
        System.out.println(".:checking permission checkPopedom()!" );    
    }    
}    

CGLibProxy dynamic proxy class

package com.fy.spring.proxy;    
    
import java.lang.reflect.Method;    
    
import net.sf.cglib.proxy.Enhancer;    
import net.sf.cglib.proxy.MethodInterceptor;    
import net.sf.cglib.proxy.MethodProxy;    
    
/**   
 * Instance of CGLibProxy dynamic proxy class   
 *     
 *    
 */    
public class CGLibProxy implements MethodInterceptor {    
    
    private Object targetObject; // CGLib needs the proxy target object    
    
    public Object createProxyObject(Object obj) {    
        this.targetObject = obj;    
        Enhancer enhancer = new Enhancer();    
        enhancer.setSuperclass(obj.getClass());    
        enhancer.setCallback(this);    
        Object proxyObj = enhancer.create();    
         return proxyObj; // return proxy object     
    }    
    
    public Object intercept(Object proxy, Method method, Object[] args,    
            MethodProxy methodProxy) throws Throwable {    
        Object obj = null ;    
         if ("addUser".equals(method.getName())) { // filter method     
            checkPopedom(); // check permissions     
        }    
        obj = method.invoke(targetObject, args);    
        return obj;    
    }    
    
    private void checkPopedom() {    
        System.out.println( ".:Check permissions checkPopedom()!" );    
    }    
}    

Test class:

public  class Customer {    
    
    public static void main(String[] args) {    
    
        UserManager userManager = (UserManager) new CGLibProxy()    
                .createProxyObject(new UserManagerImpl());    
        System.out.println("-----------CGLibProxy-------------");    
        userManager.addUser("tom", "root");    
        System.out.println("-----------JDKProxy-------------");    
        JDKProxy jdkPrpxy = new JDKProxy();    
        UserManager userManagerJDK = (UserManager) jdkPrpxy    
                .newProxy(new UserManagerImpl());    
        userManagerJDK.addUser("tom", "root");    
    }    
    
}   

operation result:

-------------CGLibProxy-------------     
Check permissions checkPopedom() !    
Use the UserManagerImpl.addUser() method!     
-----------JDKProxy-------------     
Check permissions checkPopedom() !     
UserManagerImpl.addUser() method was used!

cglib dynamic proxy

1. CGlib is a powerful, high-performance, high-quality code generation class library. CGLib must depend on the class library of CGLib. It can extend Java classes and implement Java interfaces at runtime. 
2. The proxy class generated by CGlib is a subclass of the target class. 
3. No interface is required to generate proxy classes 
with CGlib. 4. The proxy classes generated by CGLib rewrite each method of the parent class. 
5. The content of the intercept method in the interceptor is exactly the method body in the proxy class

JDK proxy is a library that does not need to come from a third party. As long as the JDK environment is required, it can be proxyed. It has several requirements
* Implement InvocationHandler 
* Use Proxy.newProxyInstance to generate proxy objects
* The proxy object must implement the interface

Two proxy modes of spring

    1. If the target object implements several interfaces, spring uses the JDK's java.lang.reflect.Proxy class proxy. 
      Pros: Makes the system more loosely coupled because of the interface 
      Cons: Creates an interface for each target class
    2. If the target object does not implement any interface, spring uses the CGLIB library to generate a subclass of the target object. 
      Advantages: Because the proxy class and the target class are inherited, there is no need for the existence of an interface. 
      Disadvantages: Because no interface is used, the coupling of the system is not as good as that of using JDK's dynamic proxy.

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325570736&siteId=291194637