Detailed java static and dynamic proxies

Catalog

1. Static Agent

2. Dynamic Agent

(1) JDK dynamic proxy

(2) Cglib Dynamic Agent

(3) Differences between jdk dynamic proxy and cglib dynamic proxy

Proxy is a common design pattern for providing a proxy for other objects to control access to an object.The proxy class is responsible for preprocessing messages for the delegate class (the proxy class), filtering and forwarding messages, and subsequent processing of messages after they are executed by the delegate class.

To maintain consistent behavior, proxy and delegate classes usually implement the same interface, so there is no difference between them in the view of visitors.Through the middle layer of proxy class, direct access to the delegate class objects can be effectively controlled, and the delegate class objects can also be well hidden and protected. At the same time, space is reserved for implementing different control strategies, which gives more flexibility in design.The Java dynamic proxy mechanism neatly and perfectly practices the design concept of proxy mode in a clever way.

Proxy, in short, both proxy and delegate classes implement the same interface, proxy classes execute methods in delegate classes implemented from the same interface instead of delegate classes, and proxy classes can do other appropriate processing before and after they execute methods instead of delegate classes.

1. Static Agent

  • Features: Proxy and delegate classes are determined during compilation.
  • Examples of static proxies
/**
 *      Static Proxy:
 *      Features: Proxy and proxy classes are determined during compilation
 */
interface ClothFactory{
    void produceCloth();
}
//Proxy Class
class NikeClothFactory implements ClothFactory{
    public void produceCloth() {
        System.out.println("Nike The factory produces a batch of sportswear.");
    }
}
//proxy class
class ProxyClothFactory implements ClothFactory{
    //Instantiate with a proxy object
    private ClothFactory clothFactory = null;
    public ProxyClothFactory(ClothFactory clothFactory){
        this.clothFactory = clothFactory;
    }
    public void produceCloth() {
        System.out.println("Agent factory does some preparatory work");
        clothFactory.produceCloth();
        System.out.println("Agent factory does some finishing work");
    }
}
public class StaticProxyTest {
    public static void main(String[] args) {
        //Create an object of a proxy class
        ClothFactory nikeClothFactory = new NikeClothFactory();
        //Object to create proxy class
        ProxyClothFactory proxyClothFactory = new ProxyClothFactory(nikeClothFactory);
        proxyClothFactory.produceCloth();
    }
}

2. Dynamic Agent

Dynamic proxy refers to a method by which a client invokes other objects through a proxy class, and dynamically creates a proxy object of the target class when the program runs.

(1) JDK dynamic proxy

  • jdk dynamic proxy related classes and interfaces

java.lang.reflect.Proxy: This is the main class of the Java dynamic proxy mechanism, which provides a set of static methods for dynamically generating proxy classes and objects for a set of interfaces.

  • Proxy Static method of

         // Method 1: This method is used to get the call handler associated with the specified proxy object
         static InvocationHandler getInvocationHandler(Object proxy) 
 
        // Method 2: This method is used to obtain a class object associated with a dynamic proxy class for a specified class loader and a set of interfaces
         static Class getProxyClass(ClassLoader loader, Class[] interfaces) 
 
        // Method 3: This method is used to determine if the specified class object is a dynamic proxy class
         static boolean isProxyClass(Class cl) 
 
       // Method 4:This method is used to generate a dynamic proxy class instance for a specified class loader, a set of interfaces, and a calling processor
          static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)

  • InvocationHandler Core approach

       //When we call method a through an object of a proxy class, we automatically call the following methods: invoke()
       //The function of method a to be executed by the proxy class is declared in invoke()

   Object invoke(Object proxy, Method method, Object[] args)

  • Two issues to be solved for jdk to implement dynamic proxy

Question 1: How to dynamically create a proxy class and its objects based on the delegate class loaded into memory;

Solution: Reflection.Returns a proxy class object through reflection.

//Agent Factory
class ProxyFactory{
    //When this method is called, the incoming delegate class object returns the proxy class object
    Public static Object getProxyInstance (Object obj) {//obj is a delegate class object
        MyInvocationHandler handler = new MyInvocationHandler(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }
}

Question 2: How to dynamically invoke a method with the same name in a delegate class when accessing method a through an object of the proxy class.

Solution: Implement the InvocationHandler interface and override the invoke method.When method a is called through a proxy class object, the invoke party method is automatically invoked, so the functional logic of the method a to be executed by the delegate class can be written in the invoke method.

class MyInvocationHandler implements InvocationHandler{
    private Object obj;
    public MyInvocationHandler(Object obj){
        this.obj = obj;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Processing before a proxy class invokes a method of a delegate class");
        Object returnValue = method.invoke(obj, args);
        System.out.println("Processing after a proxy class invokes a method of a delegate class");
        return returnValue;
    }
}

 

  • jdk dynamic proxy full code implementation
/**
 *   Dynamic Proxy
 *   Features: Proxy classes can only be determined at runtime
 **/
interface Human{
    void getBrief(String brief);
    void eat(String food);
}
//Delegate Class
class SuperMan implements Human{
    public void getBrief(String brief) {
        System.out.println("Superman's belief is"+brief);
    }
    public void eat(String food) {
        System.out.println("Superman likes to eat"+food);
    }
}
//Agent Factory
class ProxyFactory{
    //When this method is called, the incoming delegate class object returns the proxy class object
    public static Object getProxyInstance(Object obj){  //obj is a delegate class object
        MyInvocationHandler handler = new MyInvocationHandler(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),handler);
    }
}
class MyInvocationHandler implements InvocationHandler{
    private Object obj;
    public MyInvocationHandler(Object obj){
        this.obj = obj;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Processing before a proxy class invokes a method of a delegate class");
        Object returnValue = method.invoke(obj, args);
        System.out.println("Processing after a proxy class invokes a method of a delegate class");
        return returnValue;
    }
}
public class DynamicProxyTest {
    public static void main(String[] args) {
        SuperMan man = new SuperMan();
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(man);
        proxyInstance.getBrief("safeguard world peace");
        System.out.println("=============================");
        proxyInstance.eat("Core");
    }
}

(2) Cglib Dynamic Agent

  • Cglib can extend java classes and java interfaces during runtime.What makes cglib more powerful than a jdk dynamic proxy is that it can take over not only the methods of interface classes, but also the methods of common classes (a jdk dynamic proxy can only take over the methods of interface classes).The cglib dynamic proxy is also used in Spring and Hibernate.

  • At the bottom of cglib is the java byte code framework, ASM.

  • CGLIB Detailed Learning Reference: https://blog.csdn.net/weixin_40391011/article/details/104025265

(3) Differences between jdk dynamic proxy and cglib dynamic proxy

 

  • Principle difference:

The jdk dynamic proxy generates an anonymous class of proxy class interface using reflection mechanism, and calls InvokeHandler to process it before calling specific methods. The core is to implement the InvocationHandler interface, use invoke method for face-oriented processing, and call appropriate notifications.

The cglib dynamic proxy uses the asm open source package to load the class file of the proxy object and process it by modifying its byte code to generate subclasses.The core is to implement the MethodInterceptor interface, use intercep() method for face-to-face processing, and call appropriate notifications.

1. If the target object implements the interface, spring implements AOP by default using JDK dynamic proxy;

2. spring can also force CGLIB to implement AOP if the target object implements the interface;

3. If the target object does not implement the interface, cglib must be used to implement dynamic proxy, of course Spring can switch between JDK dynamic proxy and CGLIB dynamic proxy.

  • Performance differences:

The bottom level of CGLIB uses byte code operation framework ASM and byte code technology to generate proxy classes, which are more efficient than JDK dynamic proxy before jdk6.It is important to note that CGLIB cannot proxy final-modified classes and methods because CGLIB works by dynamically generating subclasses of proxied classes.

After JDK6,JDK7,JDK8 are optimized step by step for JDK dynamic proxy, the efficiency of JDK dynamic proxy is higher than CGLIB in the case of fewer calls. JDK dynamic proxy is less efficient only in the case of a large number of calls, but after JDK8, the efficiency of JDK dynamic proxy is higher than CGLIB.

  • Their limitations:

1. The dynamic proxy of JDK can only proxy classes that implement interfaces, and classes that do not implement interfaces cannot proxy JDK dynamically.

2. The principle of cglib is to generate a subclass of the target class and override its methods for enhancements, but because inheritance is used, final-modified classes and methods cannot be proxied.(

  • Respective advantages

1. JDK Dynamic Proxy Advantage: Minimizing dependencies means less development and maintenance, and JDK itself may be more reliable than cglib.Smooth JDK version upgrades, while the byte code class libraries often need to be updated to ensure they are usable on new versions of java.Code implementation is simple.

2. Advantages of cglib dynamic proxy: There is no limitation on the implementation of the interface.High performance.

 

 

 

 

 

 

 

Twenty-four original articles were published. Zambed 0. Visits 812
Private letter follow

Keywords: JDK Java Spring less

Added by xardas on Sat, 18 Jan 2020 03:49:06 +0200