The difference between static agent and dynamic agent

The difference between static agent and dynamic agent

According to the creation period of the agent, the agent class can be divided into two types:
Static: programmers create proxy classes or specific tools to automatically generate source code and then compile it. The. Class file of the proxy class already exists before the program runs.
Dynamic: it is created dynamically by using reflection mechanism when the program is running.

Advantages and disadvantages of static proxy class

advantage:
Proxy makes the client do not need to know what the implementation class is and how to do it. The client only needs to know the proxy (decoupling). For the above client code, newUserManagerImpl() can be hidden by the application factory.

Disadvantages:
1) The proxy class and the delegate class implement the same interface, and the proxy class implements the same method through the delegate class. This leads to a lot of code duplication. If a method is added to the interface, all proxy classes need to implement this method in addition to all implementation classes. It increases the complexity of code maintenance.
2) Proxy objects only serve one type of objects. If you want to serve multiple types of objects. It is bound to proxy for each object. Static proxy is incompetent when the program scale is a little large. The above code only provides a proxy for the access of the UserManager class, but if we need to provide a proxy for other classes such as the Department class, we need to add the proxy class of the Department again.
Examples show that agents can manage the implementation classes uniformly, for example, before calling specific implementation classes, we need to print logs and other information, so we only need to add a proxy class, add the function of print log in the proxy class, and then call the implementation class, thus avoiding modifying the concrete implementation class. Meet what we call the opening and closing principle. However, if you want each implementation class to add the function of printing logs, you need to add multiple agent classes, and each method in the agent class needs to add the function of printing logs (in the above agent methods, the function of printing logs needs to be added to delete, modify, and query)
That is, static proxy classes can only serve specific interfaces (services). If you want to serve multiple interfaces, you need to establish many proxy classes.

Dynamic agent benefits:

Compared with static proxy, the biggest advantage of dynamic proxy is that all methods declared in the interface are transferred to a centralized method of the calling processor (InvocationHandler.invoke). In this way, when there are a large number of interface methods, we can handle them flexibly without transferring each method like a static agent. Moreover, the application of dynamic agent makes our class responsibilities more single and reusable

According to the above introduction, you will find that each proxy class can only serve one interface, so there will be many proxy classes in program development
So we will find a way to complete all the proxy functions through a proxy class, so we need to use dynamic proxy.
Dynamic proxy implements dynamic proxy through reflection mechanism at runtime and can proxy various types of objects. To implement dynamic proxy mechanism in Java, it needs the support of java.lang.reflect.InvocationHandler interface and java.lang.reflect.Proxy class

The java.lang.reflect.InvocationHandler interface is defined as follows:

//Object proxy: the proxy object  
//Method: method to call  
//Object[] args: required parameters for method call  
public interface InvocationHandler {  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;  
}  

The java.lang.reflect.Proxy class is defined as follows:

//Classloader: loader of class  
//Class<?>  Interfaces: get all interfaces  
//InvocationHandler h: get the instance of subclass of InvocationHandler interface  
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException  

Concrete implementation class

public class UserManagerImpl implements UserManager {  
  
    @Override  
    public void addUser(String userId, String userName) {  
        System.out.println("UserManagerImpl.addUser");  
    }  
  
    @Override  
    public void delUser(String userId) {  
        System.out.println("UserManagerImpl.delUser");  
    }  
  
    @Override  
    public String findUser(String userId) {  
        System.out.println("UserManagerImpl.findUser");  
        return "Zhang San";  
    }  
  
    @Override  
    public void modifyUser(String userId, String userName) {  
        System.out.println("UserManagerImpl.modifyUser");  
  
    }  
  
}  

Dynamically create classes for proxy objects

//Dynamic proxy classes can only proxy interfaces (abstract classes are not supported). Proxy classes need to implement InvocationHandler class and invoke method. The invoke method is called when calling all methods of the proxy interface. The value returned by the invoke method is an implementation class of the proxy interface  
     
public class LogHandler implements InvocationHandler {  
  
    // Target object  
    private Object targetObject;  
    //Binding relationship, that is, when the methods associated with which interface (bound to the specific implementation class) will be called, the invoke method is executed.              
    public Object newProxyInstance(Object targetObject){  
        this.targetObject=targetObject;  
        //This method is used to generate a dynamic proxy class instance for the specified class loader, a set of interfaces and the calling processor    
        //The first parameter specifies the class loader that generates the proxy object, which needs to be specified as the same class loader as the target object  
        //The second parameter needs to implement the same interface as the target object, so you only need to get the implementation interface of the target object  
        //The third parameter indicates which InvocationHandler's invoke method needs to be executed when these intercepted methods are intercepted  
        //Returns a proxy object based on the incoming destination  
        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),  
                targetObject.getClass().getInterfaces(),this);  
    }  
    @Override  
    //The method of the associated implementation class will be executed when called  
    /*InvocationHandler Interface method. Proxy represents proxy, method represents the method called by the original object, and args represents the parameters of the method*/  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        System.out.println("start-->>");  
        for(int i=0;i<args.length;i++){  
            System.out.println(args[i]);  
        }  
        Object ret=null;  
        try{  
            /*Processing log information before calling the original object method*/  
            System.out.println("satrt-->>");  
              
            //Call target method  
            ret=method.invoke(targetObject, args);  
            /*Processing log information after original object method call*/  
            System.out.println("success-->>");  
        }catch(Exception e){  
            e.printStackTrace();  
            System.out.println("error-->>");  
            throw e;  
        }  
        return ret;  
    }  
  
}  

The proxy object targetObject is passed in through parameters. We get the ClassLoader object through targetObject.getClass().getClassLoader(), then get all the interfaces it implements through targetObject.getClass().getInterfaces(), and then wrap the targetObject into the LogHandler object that implements the InvocationHandler interface. Through the newProxyInstance function, we get a dynamic proxy object.

Client code

public class Client {  
  
    public static void main(String[] args){  
        LogHandler logHandler=new LogHandler();  
        UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());  
        //UserManager userManager=new UserManagerImpl();  
        userManager.addUser("1111", "Zhang San");  
    }  
}  

We can see that we can proxy different types of objects through LogHandler. If we implement external interfaces through dynamic proxy, all function calls will eventually be forwarded through the invoke function. Therefore, we can do some operations we want to do here, such as log system, transaction, interceptor, permission control, etc. This is the basic principle of AOP (aspect oriented programming).

Keywords: Java Interview Dynamic Proxy

Added by kb0000 on Mon, 08 Nov 2021 11:49:24 +0200