1. Agent mode
An agent is a person or an institution acting on behalf of another person or institution. In some cases, a client does not want or cannot reference an object directly, and a proxy object can act as an intermediary between the client and the target object.
The proxy pattern provides a proxy object for an object, and the proxy object controls the reference to the original object.
Example in real life: You are busy working overtime during the New Year and have no time to buy train tickets. At this time, you can call the nearby ticket center and ask them to buy you a train ticket home. Of course, this will add extra labor fees. But it should be clear that the ticket center itself does not sell tickets. Only the train station actually sells tickets. The tickets the ticket center sells to you are actually realized through the train station. This is very important!
In the above example, you are the "customer", the ticket center is the "agent role", the train station is the "real role", and selling tickets is called the "abstract role"!
Agent mode JAVA code example:
Abstract role: abstract class or interface
Copy the code code as follows:
interfaceBusiness
{
void doAction();
}
Real role: truly implements the business logic interface
Agent role: It does not implement the business logic interface, but calls the real role to implement it.
Copy the code code as follows:
class BusinessImplProxy implements Business
{
private BusinessImpl bi;
public void doAction()
{
if (bi==null)
{
bi = new BusinessImpl();
}
doBefore();
bi.doAction();
doAfter();
}
public void doBefore()
{
System.out.println("Preprocessing!");
}
public void doAfter()
{
System.out.println("Post-processing!");
}
}
//test class
class Test
{
public static void main(String[] args)
{
//Reference variables are defined as abstract role types
Business bi = new BusinessImplProxy();
bi.doAction();
}
}
Copy the code code as follows:
<span></span>
Therefore, with the support of JVM, proxy classes ("agent roles") can be dynamically generated at runtime, and we can solve the problem of code expansion in the above proxy mode. After using dynamic proxy, "agent roles" will not need to be generated manually. , which is dynamically generated by the JVM at runtime by specifying three parameters: class loader, interface array, and call handler.
Dynamic proxy mode JAVA code example:
Copy the code code as follows:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
//Abstract role: The implementation of java dynamic proxy currently only supports interfaces and does not support abstract classes
interface BusinessFoo
{
void foo();
}
interfaceBusinessBar
{
String bar(String message);
}
//Real role: Really implement business logic methods
class BusinessFooImpl implements BusinessFoo
{
public void foo()
{
System.out.println("BusinessFooImpl.foo()");
}
}
class BusinessBarImpl implements BusinessBar
{
public String bar(String message)
{
System.out.println("BusinessBarImpl.bar()");
return message;
}
}
//Dynamic role: dynamically generate proxy class
class BusinessImplProxy implements InvocationHandler
{
privateObject obj;
BusinessImplProxy() {
}
BusinessImplProxy(Object obj) {
this.obj = obj;
}
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable
{
Object result = null;
doBefore();
result = method.invoke(obj,args);
doAfter();
return result;
}
public void doBefore(){
System.out.println("do something before Business Logic");
}
public void doAfter(){
System.out.println("do something after Business Logic");
}
public static Object factory(Object obj)
{
Class cls = obj.getClass();
return Proxy.newProxyInstance(cls.getClassLoader(),cls.getInterfaces(),new BusinessImplProxy(obj));
}
}
//test class
public class DynamicProxy
{
public static void main(String[] args) throws Throwable
{
BusinessFooImpl bfoo = new BusinessFooImpl();
BusinessFoo bf = (BusinessFoo)BusinessImplProxy.factory(bfoo);
bf.foo();
System.out.println();
BusinessBarImpl bbar = new BusinessBarImpl();
BusinessBar bb = (BusinessBar)BusinessImplProxy.factory(bbar);
String message = bb.bar("Hello,World");
System.out.println(message);
}
}
Program flow description:
new BusinessFooImpl(); creates a "real role", passes it to the factory method BusinessImplProxy.factory(), and then initializes the "invocation processor" - the class that implements InvocationHandler. And returns a dynamically created proxy class instance. Since the "agent role" must also implement the business logic methods provided by the "abstract role", it can be transformed down to BusinessBar and assigned to the reference bb pointing to the BusinessBar type.
The newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) method allows programmers to specify parameters and dynamically return the required proxy class, while the invoke(Object proxy, Method method, Object[] args) method is used by the JVM. Called dynamically at runtime. When executing the "bb.bar("Hello,World");" method, the JVM dynamically assigns an "invocation handler", passes parameters to the outer invoke, and calls method.invoke(obj, args) to actually execute it!
The BusinessImplProxy.Factory static method is used to dynamically generate proxy classes ("agent roles"). The proxy roles are dynamically generated at runtime based on different business logic interfaces BusinessFoo and BusinessBar. "Abstract role", "agent role" and invocation handler (class that implements the InvocationHandler interface) can all be changed, so JAVA's dynamic proxy is very powerful.