Introduction:
The agent mode belongs to the structural mode. Its function is to provide a kind of agent for other objects to control the access to this object. Common implementation methods include static agent and dynamic agent. AOP in Spring is based on the proxy pattern.
The specific implementation and test are as follows:
1. Static agent
/** * Define the function interface, and let the proxy and the proxied object implement * @author dedu * */ public interface ISubject { void request(); } /** * The agent performs the actual request processing and returns the result to the agent * @author dedu * */ public class RealSubject implements ISubject { @Override public void request() { System.out.println("Processing by actual request processor"); } } /** * Static proxy: an agent's reference is preserved in the proxy. When the agent is invoked, the internal personalization is processed and the corresponding function of the agent is called. * @author dedu * */ public class Proxy implements ISubject { private ISubject rs; public Proxy(ISubject rs) { super(); this.rs = rs; } @Override public void request() { System.out.println("Request receiving by agent"); rs.request(); System.out.println("The agent calls the end of the actual request"); } }
test
public static void main(String[] args) { ISubject sub = new RealSubject(); Proxy proxy = new Proxy(sub); proxy.request(); }
2. Dynamic agent
/** * Define the function interface, and let the proxy and the proxied object implement * @author dedu * */ public interface ISubject { void request(); } /** * The agent performs the actual request processing and returns the result to the agent * @author dedu * */ public class RealSubject implements ISubject { @Override public void request() { System.out.println("Processing by actual request processor"); } }
2.1 implementation based on JDK
public class SubjectHandler implements InvocationHandler { private ISubject subject; public SubjectHandler(ISubject subject) { super(); this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("JDK The agent receives the request and calls the agent for processing"); Object result = method.invoke(subject, args); /* if ("checkUserPower".equals(method.getName())) { //You can also personalize a method //Other treatments } */ System.out.println("JDK The agent receives the processing result and returns the result object"); return result; } }
2.2 CGLib based implementation
/** * The Jar package is cglib-2.2.2 and asm-3.3.1 * @author dedu * */ public class SubjectInterceptor implements MethodInterceptor { private ISubject subject; public SubjectInterceptor(ISubject subject) { this.subject = subject; } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.out.println("CGLib The agent receives the request and calls the agent for processing"); Object result = arg1.invoke(this.subject, arg2); /* if ("checkUserPower".equals(method.getName())) { //You can also personalize a method //Other treatments } */ System.out.println("CGLib The agent receives the processing result and returns the result object"); return result; } public Object createProxyInstance() { Enhancer eh = new Enhancer(); eh.setSuperclass(this.subject.getClass()); eh.setCallback(this); return eh.create(); } }
test
public static void main(String[] args) { //JDK agent test ISubject realSubject = new RealSubject(); SubjectHandler handler = new SubjectHandler(realSubject); ISubject dynamicProxy = (ISubject) Proxy.newProxyInstance(ISubject.class.getClassLoader(), new Class[] {ISubject.class}, handler); dynamicProxy.request(); //CGLib proxy test ISubject trueSubject = new RealSubject(); SubjectInterceptor cglibProxy = new SubjectInterceptor(trueSubject); ISubject proxy = (ISubject) cglibProxy.createProxyInstance(); proxy.request(); }
3. summary:
Static proxy: keeping a reference in the proxy allows the proxy to access the entity and provide the same interface as the entity.
Dynamic proxy: the proxy class is created when the program is running. The common implementation methods include the dynamic proxy class (subclass generated by reflection mechanism) and CGLib dynamic proxy class (subclass generated by byte code modified by ASM).
- The JDK agent can only generate agents for classes that implement interfaces.
- CGLib can generate a class by proxy directly, but it requires that the class is not final and the proxy method is not final/static/private.