The concept of an agent: a simple understanding is that by creating a proxy object for an object, we do not directly reference the original object, but rather the proxy object created to control the reference to the original object.
Dynamic Proxy: refers to the dynamic generation of the Java reflection mechanism when the program is running, without having to write code manually. Dynamic proxies not only simplify programming, but also improve the scalability of software systems, because the Java reflection mechanism can generate any type of dynamic proxy class.
Agent Principle : The proxy object contains a reference to the real object, so that the real object can be manipulated, while the proxy object provides the same interface as the real object to replace the real object at any moment. At the same time, the proxy object can attach other actions when performing the real object operation, which is equivalent to encapsulating the real object.
The following is a simple example of how to implement the agent based on the JDK dynamic agent and Cglib.
Agent interface UserService:
1 Package com.liang.test; 2 3 Public Interface UserService {4 Public void say (String arg); 5 }
UserService implementation class Userserviceimpl:
1 Package com.liang.test; 2 3 Public class Implements UserService {4 @Override5public void say (String Arg) {6 System.out.println ("Hello, I am" + arg); 7 }8 }
The JDK generates dynamic proxy classes and dynamic proxy objects through the proxy class and a Invocationhandler interface under the Java.lang.reflect package.
First, create a call controller object that implements the Invocationhandler interface Myinvocationhandler: (When executing the target method in the dynamic proxy object, Will actually replace the Invoke method called Myinvocationhandler)
1 Packagecom.liang.test;2 3 ImportJava.lang.reflect.InvocationHandler;4 ImportJava.lang.reflect.Method;5 6 Public classMyinvocationhandlerImplementsInvocationhandler {//Implement Invocationhandler7 8 PrivateObject object;//The object being proxied9 Ten PublicMyinvocationhandler (Object object) {//receiving proxied Objects One This. Object =object; A } - @Override - Publicobject Invoke (Object proxy, Method method, object[] args) the throwsThrowable {//the Say () method is replaced to perform the current method, where additional functionality can be added to enhance the target method -System.out.println ("Before Method")); -Object obj = Method.invoke (object, args);//calling UserService's Say () method through reflection -System.out.println ("After Method"); + returnobj; - } + A}
Create a dynamic proxy class for UserService by using proxy with Myinvocationhandler:
1 Packagecom.liang.test;2 3 ImportJava.lang.reflect.InvocationHandler;4 ImportJava.lang.reflect.Proxy;5 6 Public classTestproxy {7 8 Public Static voidMain (string[] args) {9UserService UserService =NewUserserviceimpl ();TenInvocationhandler handler =NewMyinvocationhandler (userservice); One AUserService proxy =(UserService) proxy.newproxyinstance (Userservice.getclass () - . getClassLoader (), Userservice.getclass (). Getinterfaces (), - handler); theProxy.say ("Monkey King");//Invoking proxy instances - } - -}
Operation Result:
Before Methodhello, I am Monkey King after method
You can see that the say method that executes the proxy instance executes the Myinvocationhandler invoke () method.
The cglib uses a very low-level bytecode technique to create a subclass for the proxy object and uses the technique interception technology in subclasses to intercept calls to all parent methods and to inject the enhanced code. Examples of cglib implementing dynamic proxies are as follows:
1 Packagecom.liang.test;2 3 ImportJava.lang.reflect.Method;4 5 ImportNet.sf.cglib.proxy.Enhancer;6 ImportNet.sf.cglib.proxy.MethodInterceptor;7 ImportNet.sf.cglib.proxy.MethodProxy;8 9 Public classCglibproxyImplementsMethodinterceptor {Ten One PrivateEnhancer enhancer =Newenhancer (); A - PublicObject getproxy (Class clazz) { -Enhancer.setsuperclass (Clazz);//set up classes that need to create subclasses theEnhancer.setcallback ( This); - returnEnhancer.create ();//To create a child class instance - } - + @Override - PublicObject Intercept (Object object, method, object[] args, +Methodproxy proxy)throwsThrowable {//intercepts all method calls in the parent class ASystem.out.println ("Cglib:before method")); atObject obj = Proxy.invokesuper (object, args);//calling methods in a parent class through a proxy class -System.out.println ("Cglib:after method")); - returnobj; - } - -}
Test code:
1 Packagecom.liang.test;2 3 Public classTestproxy {4 5 Public Static voidMain (string[] args) {6Cglibproxy proxy =Newcglibproxy ();7Userserviceimpl Userserviceimpl = (Userserviceimpl) proxy.getproxy (Userserviceimpl.class);8Userserviceimpl.say ("Monkey King"));9 }Ten One}
Operation Result:
Cglib:before Methodhello, I am Monkey King Cglib:after method
Summary: The most common application of the JDK dynamic agent and the Cglib dynamic agent is the underlying implementation of the SPRINGAOP, and the JDK-based dynamic agent takes less time than cglib to create the proxy object, but the JDK can only create proxy instances for the interface. This can be seen from newproxyinstance (ClassLoader loader, class[] interfaces, Invocationhandler h): The second entry is a list of interfaces implemented by the proxy sample. The proxy object created by Cglib is higher than the proxy object created by the JDK, but takes a relatively long time, and because Cglib generates proxy objects in a way that dynamically creates subclasses, it cannot be proxied by Cglib for a method that is decorated by the final. Based on this, we are more suitable for the proxy object of Singgleton or the agent with the instance pool to use the Cglib Dynamic Agent technology, for each new instance of the general use of the JDK dynamic Agent technology.
The study materials refer to:
1. "Proficient in spring2.x-enterprise application development detailed"--Chen Xionghua;
2.HTTP://REJOY.ITEYE.COM/BLOG/1627405--JDK Dynamic Agent Implementation principle
Java Learning: JDK Dynamic agent and Cglib dynamic agent