the basic composition of the agent:
Agent mode, basically have Subject role,realsubject role,proxy role. Where:the subject role is responsible for defining the interface that the Realsubject and proxy roles should implement, and the realsubject role is used to actually complete the business service function ; The proxy role is responsible for requesting the request , calling the Realsubject corresponding request function to realize the business function , do not really do business .
The above proxy structure diagram is a typical static proxy pattern :
When this proxy relationship is specified in the code phase, the proxy class is compiled into a class file by the compiler, and the class already exists when the system is running. While this static proxy mode has great advantages in accessing inaccessible resources and enhancing existing interface business functions, the large use of this static proxy will increase the size of the classes within our system and is not easy to maintain, and since the functions of proxy and realsubject are essentially the same, Proxy is only played the role of intermediary, the presence of such agents in the system, resulting in a system structure is more bloated and loose .
In order to solve this problem, there is the idea of dynamically creating a proxy: In the running state, where agents are required, according to subject and Realsubject, dynamically create a proxy, after use, will be destroyed, so you can avoid the proxy The class of the character is jumbled up in the system.
The origin of the Invocationhandler role:
Think carefully about the agent proxy role in proxy mode. The proxy role in executing the agent business is nothing more than doing some "extra" business before or after invoking the real business.
As you can see, the logic of the proxy class processing is simple: do some extra business before calling a method and after the method . Another idea is to do some extra business before or after the method that triggers the real role . Then, in order to construct a proxy class with generality and simplicity, all the triggering real-role actions can be given to a trigger manager, which allows the manager to manage the trigger uniformly. This manager is invocation Handler.
The dynamic proxy pattern has a slightly different structure than the static proxy pattern above, and introduces a invocationhandler role.
First explain the role of Invocationhandler:
In a static proxy, the methods in proxy proxies specify the corresponding method in which a particular realsubject is called:
In the static proxy mode above, the thing that the proxy does is to invoke the method that triggers the realsubject corresponding to the different request, and the more abstract point, the thing that the proxy does; the Java Chinese method is also regarded as an object,
The basic mode of dynamic agent work is to give the implementation of its own method function to the Invocationhandler role, the external to the proxy role of each method call, the proxy role will be handed to Invocationhandler to handle, and Invocatio Nhandler the method that invokes the specific object role. As shown in the following:
in this mode: proxy proxies and realsubject should implement the same functionality, which is quite important. (The function I'm talking about here can be understood as the public method of a class.)
In object-oriented programming, if we want to agree that proxy and realsubject can achieve the same functionality, there are two ways:
A . a more intuitive way is to define a functional interface, and then have proxies and realsubject to implement this interface.
B. There is also a more obscure way of passing inheritance . because if proxy inherits from Realsubject, so proxy has the function of Realsubject,Proxy can also realize polymorphism by rewriting the method in Realsubject .
The mechanism of creating dynamic agents provided in JDK is designed by a, while Cglib is designed by B idea .
The dynamic proxy creation mechanism of the JDK ----through the interface:
For example, to create a dynamic proxy object for the Realsubject class now, the JDK will do the following:
1. get a list of all the interfaces on the Realsubject ;
2. determine the class name of the proxy class to be generated, by default: Com.sun.proxy. $ProxyXXXX;
3. dynamically create the byte code of the proxy class in the code according to the interface information that needs to be implemented ;
4. converts the corresponding byte code to the corresponding class object ;
5. Create Invocationhandler instance handler to handle all method calls of proxy ;
6. the class object of the proxy instantiates a proxy object with the handler object created as a parameter
The JDK supports dynamic proxies through the Java.lang.reflect.Proxy package, and in general we use the following Newproxyinstance method
static Object |
newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
Returns a proxy class instance for the specified interface that can assign a method call to the specified invocation handler. |
For Invocationhandler, we need to implement the following invoke methods:
When each method in the proxy object is called, the Invocationhandler invoke method is called directly inside the code, and the Invoke method distinguishes it from the method parameter passed to it by the proxy class.
Object |
invoke(Object proxy,Method method,Object[] args)
Processes the method call on the proxy instance and returns the result. |
cglib mechanism for generating dynamic proxy classes----inherited through classes:
There is a distinct feature of the mechanism provided in the JDK for generating dynamic proxy classes: A class must have an implemented interface, and the generated proxy class can only proxy a method of a class interface definition ! The more extreme scenario is that if a class does not implement an interface, then this class cannot generate dynamic proxies with the JDK!
Fortunately, we have cglib. CGLIB (Code Generation Library) is a powerful, high-performance, high-quality code generation class library that extends Java classes and implements Java interfaces at run time. ”
Cglib the pattern for creating a dynamic proxy class for a Class A is:
1. find the method definition for all non-final public types on a ;
2. convert the definitions of these methods into byte codes ;
3. convert the composed byte code into the corresponding proxy class object ;
4. Implement the Methodinterceptor interface to handle requests for all methods on the proxy class (this interface is the same as the capabilities and roles of the JDK Dynamic Agent Invocationhandler )
PackageCom.sunchao.cglibproxy;ImportJava.lang.reflect.Method;ImportCom.sunchao.jdkdyproxy.*;ImportNet.sf.cglib.proxy.Enhancer;ImportNet.sf.cglib.proxy.MethodInterceptor;ImportNet.sf.cglib.proxy.MethodProxy; Public classCglibproxy { Public StaticSubject Createcglibdynamicproxy (FinalObject Delegate) { Enhancer enhancer = new Enhancer (); Enhancer.setcallback ( New Cglibinterceptor (delegate)); enhancer.setinterfaces ( New Class<?>[]{subject.class}); Subject cglibproxy = (Subject) enhancer.create (); returnCglibproxy; } Private Static classCglibinterceptorImplements methodinterceptor {Final PrivateObject Delegate; Cglibinterceptor (Object delegate) { This. Delegate =delegate; } @Override Public Object Intercept(object arg0, Method arg1, object[] arg2, methodproxy arg3)throwsThrowable {//System.out.println ("AOP before do with the request!"); returnArg1.invoke (delegate, arg2); //System.out.println ("AOP before do with the request!"); //return null; } } Public Static voidMain (String args[]) {Subject Realsubject=NewRealsubject (); Subject Cglibproxy=Createcglibdynamicproxy (Realsubject); Cglibproxy.request (); }}
See the original: http://blog.csdn.net/luanlouis/article/details/24589193
Java Dynamic Agent