Java static \ dynamic agent

Java Agent

Before acting, we need to know what we are acting for

For example, we have an original object. We don't directly access it. We access it through an agent. The purpose of this is that we don't need to modify the original object in the future. We can implement specific methods by modifying the agent class. Let's see a specific example:

First, there must be an interface

public interface IUser {
    void show();
    
    void create();

    void update();
}

Then realize it

public class Userimpl implements IUser {
    public Userimpl(){}

    public void show(){
        System.out.println("Exhibition");
    }
    
    public void create(){
        System.out.println("newly build");
    }

    public void update(){
        System.out.println("to update");
    }
}

Another agent

public class UserProxy implements IUser{
    //This is a static proxy
    IUser user;
    public UserProxy(){}

    public UserProxy(IUser user){ this.user = user; }

    @Override
    public void show() {
        user.show();
        System.out.println("Called show");
    }
    public void create(){
        user.create();
        System.out.println("Called New");
    }

    public void update(){
        user.update();
        System.out.println("Update called");
    }
}

Then we can use it

public class ProxyTest {
    public static void main(String[] args) {
        IUser user = new Userimpl();
//        user.show();
        //Static proxy
        IUser userProxy = new UserProxy(user);//Use the proxy class to go through the methods we want to use to achieve the effect of a log
        userProxy.show();
        
 Output:
     Exhibition
     Called show

The proxy method here has nothing to do with the call itself. It can be regarded as a log recording behavior, but the behavior itself has nothing to do with my call to the show method, but the log must have, but the problem comes. What if we need too many proxies?? You can't use one method and one log format as I wrote above, so the java official has come up with another proxy method, called dynamic proxy

We can assume that the working mechanism of this dynamic agent is just for convenience

public class UserProxy implements IUser{

    IUser user;
    public UserProxy(){}
    public UserProxy(IUser user){ this.user = user; }
    
    IUser user = new Userimpl(); 
    Class c = user.getClass();
    //Using reflection to obtain method
    Method usermethod = c.getMethod("show");
    
    public void execute(){
        System.out.println("Called" + usermethod.getName());
		usermethod.invoke(user,args)//Because there is no parameter, there should be no args here
    }
    
}

(I directly typed the above code in md without importing the package)

However, we found that there is another problem. The problem of method acquisition is still miscellaneous. If we don't want show, we need to replace show or another reflection. Unfortunately, the official java has come up with a good solution to the problem of miscellaneous acquisition methods, that is, dynamic agent. Let's have a look

java.lang.reflect.Proxy//One of the ways

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

Its first two parameters can be written in a fixed way, which is easier to solve

Proxy.newProxyInstance(user.getClass().getClassLoader(),
                user.getClass().getInterfaces(),
                userinvocationhandler);

But the last processor parameter we need to care about

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class UserInvocationHandler implements InvocationHandler {
    IUser user;

    public UserInvocationHandler(){}

    public UserInvocationHandler(IUser user){
        this.user = user;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("Called" + method.getName());
        method.invoke(user,args);
        return null;
    }
}

In this case, the main method is like this

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

public class ProxyTest {
    public static void main(String[] args) {
        IUser user = new Userimpl();
        //Dynamic agent
        //Interface to proxy and things to do, classloader
        InvocationHandler userinvocationhandler = new UserInvocationHandler(user);
        IUser userproxyInstance = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(),
                new Class[]{IUser.class},
                userinvocationhandler);
        userproxyInstance.update();
    }
}

The method we can choose is proyyinstance The method name is, which is more convenient to use

Keywords: Java

Added by nafarius1357 on Thu, 24 Feb 2022 18:18:46 +0200