Agent pattern details and example code in Java
- 2020-06-03 06:25:00
- OfStack
Detailed explanation of java agent pattern
Preface:
In cases where a client does not want or cannot directly reference an object, an indirect reference can be achieved through a third party called a proxy. The proxy object can mediate between the client and the target object and can remove content and services that the client cannot see or add additional services that the client requires.
In simple terms, proxy mode is to access 1 real object through 1 proxy object and add 1 function to the object as in decorative mode 1.
Static agent
The so-called static proxy means that the proxy class already exists before the program runs, that is, the code of the proxy class is written when we write the code, while the dynamic proxy automatically generates the proxy class when the program runs.
It's too abstract to describe, but look at the code in 1 to see what's going on. Okay
main
public class Main {
public static void main(String[] args) {
Water water = new Water();
WaterProxy waterProxy = new WaterProxy(water);
waterProxy.drink();
}
}
interface
// The interface that the broker class implements with the broker class
public interface Drink {
void drink();
}
By the proxy class
// The class being represented
public class Water implements Drink {
@Override
public void drink() {
System.out.println("drink water");
}
}
The proxy class
// The proxy class
// Same as the broker class implementation 1 An interface
public class DrinkProxy implements Drink {
private Drink drinkImpl;
// Passed in through the constructor Water object
public DrinkProxy(Drink drinkImpl) {
this.drinkImpl = drinkImpl;
}
@Override
public void drink() {
// Do this before executing the method of the object being represented 1 Some of the things
System.out.println("before drink");
// Executes the methods of the proxy object
drinkImpl.drink();
// After executing the method of the object being represented 1 something
System.out.println("after drink");
}
}
The execution result
before drink
drink water
after drink
A dynamic proxy
Sometimes we just want to change the class that the proxy class is acting on, but the proxy object does exactly the same thing before and after it executes the methods of the actual object. Using static proxy can only proxy classes that implement the same interface as 1. If you want to proxy any class, you must write many duplicate proxy classes. At this point, we can use dynamic proxy. Java has provided a set of convenient tools for dynamic proxy implementation.
java. lang. reflect. Proxy can dynamically generated proxy objects in the class of methods
/**
* Returns the object that implements the specified interface, and the method that calls the proxy object is called
*InvocationHandler the invoke methods
*
* @param loader Gets the classloader used by the proxy class
* @param interfaces The interface that the proxy class is going to implement
* @param h To achieve the InvocationHandler Object of the interface
* @return Proxy objects
*/
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces, InvocationHandler h)
InvocationHandler interface
/**
* Each proxy class has one 1 An associated InvocationHandler
* When the proxy object executes 1 Method will be executed directly invoke methods
*/
public interface InvocationHandler {
/**
* @param The proxy object that calls this method
* @param method The method invoked by the proxy object
* @param args The parameters of the called method
* @return The return value of the called method
*/
public Object invoke(Object proxy, Method method, Object[] args)
}
The description is always abstract, but it's easier to understand by looking at the actual example
example
Implementation class for the InvocationHandler interface
public class CommonInvocationHandler implements InvocationHandler {
// The object being represented
private Object proxied;
public CommonInvocationHandler(Object proxied) {
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Do this before invoking the method of the object being represented 1 Some of the things
System.out.println("before doing something");
// Invokes the method of the proxy object
Object result = method.invoke(proxied, args);
// After invoking the method of the object being represented 1 Some of the things
System.out.println("after doing something");;
return result;
}
}
Main
public class Main {
public static void main(String[] args) {
// The object being represented
Water water = new Water();
// Get the proxy object dynamically
Drink waterProxy =
(Drink) Proxy.newProxyInstance(water.getClass().getClassLoader(),
water.getClass().getInterfaces(),
new CommonInvocationHandler(water));
// Call a method through a proxy object
waterProxy.drink();
}
}
The output
before doing something
drink water
after doing something
It is also possible not to have a concrete proxy object, but to get a proxy object dynamically, you must have an interface (classes that do not implement an interface can use cglib to implement dynamic proxies). A recent hit like Retrofit USES dynamic proxies to make network requests directly through a declared interface.
example
Simple simulation 1 under retrofit
POST annotations
// The interface that the broker class implements with the broker class
public interface Drink {
void drink();
}
0
Query annotations
// The interface that the broker class implements with the broker class
public interface Drink {
void drink();
}
1
Service interface
// The interface that the broker class implements with the broker class
public interface Drink {
void drink();
}
2
Main
public class Main {
public static void main(String[] args) {
// Dynamic access Service Proxy for interfaces
Service service = (Service) Proxy.newProxyInstance(Service.class.getClassLoader(),
new Class[] { Service.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Gets the relative path of the request by annotation
String retativePath = ((POST) method.getAnnotations()[0]).value();
System.out.println("relative path: " + retativePath);
// Gets a comment for the parameter
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
// Get the request parameters by annotating the parameters
for (int i = 0; i < parameterAnnotations.length; i++) {
if (parameterAnnotations[i].length != 0) {
for (int j = 0; j < parameterAnnotations[i].length; j++) {
Query query = (Query) parameterAnnotations[i][j];
System.out.println(query.value() + ": " + args[i].toString());
}
}
}
return null;
}
});
// Call the method of the proxy object
service.login("hello", "world");
}
}
Thank you for reading, I hope to help you, thank you for your support to this site!