Three Java proxy mode
Proxy mode:
Proxy (Proxy) is a design pattern that provides an additional way to access the target object; that is accessed by the target through a proxy object, the benefits of doing so are: On the basis of the target object can be achieved on additional features to enhance the operation, that is extension of the target object features.
Here to use a programming idea: Do not feel free to go at someone or modify the code already written, if the need to change the modification, the method can be extended by proxy.
To give an example to illustrate the role of the agent: Suppose we wanted to buy a ticket, then the ticket is not direct, but contact cattle, to achieve the same purpose, a person is selling tickets of the target object, and other trivial things to the his agent (cattle) to resolve. This is an example of the agent thought in reality.
Fig expressed as follows:
The key point is the agent model: proxy object and the target object, a proxy object is an extension of the target object, and calls the target object.
A static agents (like the decorator pattern)
When using static agent, need to define interfaces or parent class is the interface to achieve the same or the same parent is inherited along with the proxy object proxy object.
For the following examples to explain:
analog save action, the definition of a save operation interface, then the target object implements the interface methods.
At this point if you use a static proxy mode, you need to also realize IUserDao interface proxy object, when calling to call the target object through the proxy object method call.
It should be noted that the proxy object and the target object to implement the same interface, and the method to call the target object by calling the same method.
/ ** * Interface * / public interface IUserDao { void Save (); }
target:
/ ** * interface * target object * / public class UserDao the implements IUserDao { public void Save () { System.out.println ( "already saved data ---- ----!" ); } }
Proxy object:
/ ** * proxy object, the static agent * / public class UserDaoProxy the implements IUserDao { // receiving the target object stored Private IUserDao target; public UserDaoProxy (IUserDao target) { the this .target = target; } public void Save () { the System.out .println ( "begin transaction ..." ); target.save (); // execution of the target object's method System.out.println ( "commit the transaction ..." ); } }
test:
/ ** * test class * / public class the App { public static void main (String [] args) { // audiences UserDao target = new new UserDao (); // proxy object, the target object to the proxy object, the proxy establish relationship UserDaoProxy proxy = new new UserDaoProxy (target); proxy.save (); // a proxy execution method } }
Static proxy Summary:
1. The following functions can be done without modifying the target object, the target extensions.
2. Disadvantages: Because the proxy object needs to implement the same interface as the target object, and so many proxy class, class too, at the same time, once the interface method for increasing the target object and proxy object must be maintained.
II. Dynamic Proxy
Dynamic proxies have the following characteristics:
1. proxy object, do not need to implement the interface;
generating 2. proxy object, using the JDK API, build dynamic proxy object in memory (we need to specify where to create a proxy object / target object implements the interface type);
3. dynamic agent also called: JDK proxy interface agent;
JDK API generated proxy object
proxy class where the package: the java.lang.reflect.Proxy
JDK achieve newProxyInstance agent only need to use the method, this method requires three parameters, the wording is complete:
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )
Note that this is a static method in the Proxy class, and receives three parameters were as follows:
ClassLoader loader,
: Specifies the current target object using the class loader, the loader is to obtain a fixedClass<?>[] interfaces,
: Type of target object implements an interface, use the generic way to confirm the type ofInvocationHandler h
: Event processing method executed when the target object, the event handler method will be triggered, the current method will execute the target object as a parameter
Sample code:
interface class and interface implementation class, the target object is the same, do not modify, on this basis, an increase of a proxy factory class (ProxyFactory.java).
The proxy class written in this place, then the test class (need to use proxy code) to establish contacts in the target object and proxy object, then the namesake of alternative methods proxy object.
Acting factory class:
/ ** * Create a dynamic proxy object * dynamic agent does not need to implement the interface, but need to specify the interface type * / public class the ProxyFactory { // maintain a target object Private Object target; public the ProxyFactory (Object target) { the this .target = target; } // for generating target object proxy object public Object getProxyInstance () { return the Proxy.newProxyInstance ( target.getClass (). getClassLoader (), target.getClass (). The getInterfaces (), new new of InvocationHandler () { @Override publicInvoke Object (Object Proxy, Method, Method, Object [] args) throws the Throwable { System.out.println ( "begin transaction 2" ); // use reflective target object execution method Object the returnValue = Method.invoke (target, args); System.out.println ( "commit transaction 2" ); return the returnValue; } } ); } }
test:
/ ** * test class * / public class the App { public static void main (String [] args) { // audiences IUserDao target = new new UserDao (); // [primitive type class cn.itcast.b_dynamic.UserDao] System.out.println (target.getClass ()); // target audience, create a proxy object IUserDao proxy = (IUserDao) new new the ProxyFactory (target) .getProxyInstance (); // class $ Proxy0 memory dynamically generated proxy object System.out.println (proxy.getClass ()); // perform the method of the proxy object [] proxy.save (); } }
Summary: proxy object does not need to implement the interface, but the target object must implement the interface, or can not use dynamic proxies
Three .Cglib agent (Based inheritance way)
The above static and dynamic agent Proxy models are required to achieve the target object is a target object interface, but sometimes the target object is just a single object, and does not implement any interfaces,
This time can be used in a class way to achieve the target object is a subclass of agents, this method is called: Cglib agent.
Cglib agent, also known as sub-class of agents, it is to build a subclass object in memory to achieve function expansion of the target object.
- JDK dynamic proxy there is a limit, that is, the use of dynamic proxy object must implement one or more interfaces, if you want the agent class does not implement the interface, you can use Cglib achieved;
- Cglib is a powerful, high-performance code generator package, it can extend and run java classes implement java interface, which is widely used in many frame AOP. Such as Spring AOP and synaop, provides a method for their interception (interception);
- Cglib underlying packet is to convert bytecode processing framework by a small block ASM bytecode and generating a new class, ASM directly discouraged. Because it requires you to be very familiar with the JVM internal structure including the format and instruction set class file.
Cglib subclass Agent Method:
1. cglib jar files need to be introduced, but the Spring core package has been included Cglib function, directly introduced into the pring-core-3.2.5.jar
can;
2. introduction of functional package, you can dynamically build the subclass in memory ;
3. Acting classes can not be final, otherwise an error;
4. If the target object is final / static, then it will not be blocked, that no additional business method executes the target object;
5. If the method is static, private proxy is not possible.
Target object class:
/ ** * target object does not implement any interface * / public class UserDao { public void Save () { System.out.println ( "already saved data ---- ----!" ); } }
Cglib proxy factory:
/ ** * Cglib subclass proxy factory * UserDao to dynamically build a subclass object in memory * / public class the ProxyFactory the implements MethodInterceptor { // maintenance target object Private Object target; public the ProxyFactory (Object target) { the this .target = target ; } // to the target object to create a proxy object public Object getProxyInstance () { // 1. tools Enhancer EN = new new Enhancer (); // 2. set the parent en.setSuperclass (target.getClass ()); / / 3. set callback en.setCallback (the this ); // 4. create a subclass (proxy object) return en.create (); } @Override public Object Intercept (Object obj, Method, Method, Object [] args, MethodProxy Proxy) throws the Throwable { System.out.println ( "begin transaction ..." ); // method to perform target object object returnValue = Method.invoke (target, args); System.out.println ( "commit the transaction ..." ); return returnValue; } }
or:
/ ** * Cglib subclass proxy factory * UserDao to dynamically build a subclass object in memory * / public class the ProxyFactory { // maintenance target object Private Object target; public the ProxyFactory (Object target) { the this .target = target; } // create a proxy object to the target object public Object getProxyInstance () { // 1. tools Enhancer EN = new new Enhancer (); // 2. set the parent en.setSuperclass (target.getClass ()); // . 3 set callback en.setCallback ( new new MethodInterceptor () { public Object Intercept (Object obj, Method, Method, Object [] args, MethodProxy Proxy) throws the Throwable { System.out.println ( "begin transaction ..." ); // execution target object method Object the returnValue = Method.invoke ( target, args); System.out.println ( "commit the transaction ..." ); return returnValue; } }); // 4. create a sub-class (proxy object) return en.create (); } }
test:
/ ** * test class * / public class the App { @Test public void Test () { // audiences UserDao target = new new UserDao (); // proxy object UserDao Proxy = (UserDao) new new the ProxyFactory (target) .getProxyInstance ( ); // method of performing proxy object proxy.save (); } }
supplement:
SpringBoot mandatory use proxy Cglib
the target object into a container if there is implementation of the interface, using JDK proxies.
If the target object does not implement the interface, agents with Cglib.