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