One: Proxy mode (static proxy)
Proxy mode is one of the commonly used design patterns, and the agents we use in software design generally refer to static proxies, which are explicitly specified in code.
Static proxy consists of two parts: Business implementation class and business proxy class. The Business implementation class is responsible for the implementation of the main business methods, the business proxy class is responsible for the invocation of the business method interception, filtering, preprocessing, mainly in the method first preprocessing action, and then call the business implementation of the class method, you can also specify the operation after the call. Instead of calling the business directly through the business implementation class, we invoke the business method handled by the proxy class through the same name method as the business proxy class.
Implementation of static proxies:
1: First define an interface that describes the business logic.
package Net.battier.dao; /** * define an account interface * @author Administrator */ public interface Count { // query account public void Querycount (); // Modify account public void Updatecount (); }
2: Then, define the business implementation class to implement the business logic interface
Import Net.battier.dao.Count; /** * Delegate class (contains business logic) * * @author Administrator * */Public class Countimpl implements Count { @Override public void Querycount () { System.out.println ("View account ..."); @Override public void Updatecount () { System.out.println ("Modify account ...");} }
3: Define the Business proxy class: By combining, create a business implementation class object in the proxy class to invoke the specific business method, unify the business method by implementing the business logic interface, and implement the method of the business logic interface in the proxy class, preprocess the operation, invoke the real business method through the business implementation class object, The definition of the operation after the call.
public class Countproxy implements Count { private countimpl Countimpl; A call that combines a business implementation class object to make a real business method /** * Overrides the default constructor * * @param countimpl */public Countproxy ( Countimpl Countimpl) { This.countimpl = Countimpl; } @Override public void Querycount () { System.out.println ("Pre-processing —————— for querying accounts"); Call the Real query account method Countimpl.querycount (); System.out.println ("———————— after querying the account"); } @Override public void Updatecount () { System.out.println ("pre-processing —————— before modifying the account"); Call the real modify account operation Countimpl.updatecount (); System.out.println ("—————————— after modifying Account"); } }
4: In use, first create a business implementation class object, and then the business implementation class object as the construction parameters to create a proxy class object, and finally through the proxy class object for business method calls.
public static void Main (string[] args) { Countimpl Countimpl = new Countimpl (); Countproxy countproxy = new Countproxy (COUNTIMPL); Countproxy.updatecount (); Countproxy.querycount (); }
The disadvantage of static proxies is obvious: a proxy class can only be packaged for an implementation class of a business interface, and if there are multiple business interfaces, it is necessary to define many implementation classes and proxy classes. Also, if the proxy class is pre-processed for the business method, after the call operation is the same (for example: Before the call output prompt, after the call automatically closes the connection), there will be a lot of duplicate code for multiple proxy classes. At this point, we can define a proxy class that can proxy all of the implementation class's method invocations: Based on the incoming business implementation class and method name. -That's dynamic proxy.
Second: The first realization of dynamic agent--JDK dynamic agent
The proxy class used by the JDK dynamic agent is actually created by the JVM when the program calls to the proxy class object, and the JVM dynamically creates a class file for the proxy class and is executed by the bytecode engine, based on the incoming business implementation class object and method name, and then makes method calls through the proxy class object. What we need to do is to specify the pre-processing of the proxy class and the operation after the call.
1: First, define the business logic interface
Public interface Bookfacade {public void Addbook ();
2: Then, implement the business logic interface to create the business implementation class
public class Bookfacadeimpl implements Bookfacade { @Override public void Addbook () { System.out.println (" Increase the book Method ... "); }
3: Finally, implement call management interface Invocationhandler Create dynamic proxy class
public class Bookfacadeproxy implements Invocationhandler {Private Object target;//This is actually a business implementation class object that is used to invoke a specific business method/ * * Bind the business object and return a proxy class */public object bind (object target) {this.target = target; Receive business implementation class object parameters//By reflection mechanism, a proxy class object instance is created and returned. When a user makes a method call using//To create a proxy object, it is necessary to pass the class loader for that business class (to get the metadata for the business implementation class, the wrapper method is to call the real business method), the interface, the handler implementation class return Proxy.newproxyinstanc E (Target.getclass (). getClassLoader (), Target.getclass (). Getinterfaces (), this); }/** * Wrapper call Method: Preprocessing, post-processing after call */public object Invoke (object proxy, Method method, object[] args) Throws Throwable {Object result=null;
System.out.println ("preprocessing Operation ——————"); Call the real business method Result=method.invoke (target, args);
System.out.println ("post-call processing ——————"); return result; } }
4: When used, first create a business implementation class object and a proxy class object, then define the interface reference (which is used here to transform) and assign it with the return value of the proxy object. BIND (Business implementation class object). Finally, the business method can be invoked through an interface reference. (The interface reference really points to a proxy class object that is bound to a business class, so the proxy method is called through the interface method name)
public static void Main (string[] args) { Bookfacadeimpl bookfacadeimpl=new bookfacadeimpl (); Bookfacadeproxy proxy = new Bookfacadeproxy (); Bookfacade Bookfacade = (bookfacade) proxy.bind (Bookfacadeimpl); Bookfacade.addbook (); }
The proxy object of the JDK dynamic agent is created using the interface implemented by the business implementation class as a parameter (because the proxy method later needs to be called based on the method name within the interface). The JDK dynamic proxy cannot be used if the business implementation class does not implement the interface but defines the business method directly. Also, if there are new methods in the business implementation class that are not available in the interface, these methods cannot be proxied (because they cannot be called).
Three: The second realization of dynamic agent--cglib
Cglib is implemented for the class to implement the proxy, the principle is to create a subclass of the specified business class, and override the business method to implement the proxy. Because inheritance is used, the final decorated class cannot be proxied.
1: First define the business class, without implementing interface (of course, implementation interface can, not affect)
public class BookFacadeImpl1 {public void Addbook () { System.out.println ("new book ...");} }
2: Implement Methodinterceptor method Proxy interface, create proxy class
public class Bookfacadecglib implements Methodinterceptor {Private Object target;//Business class object for real business method calls in proxy methods Equivalent to the Bind public object getinstance (object target) {This.target = target) in the JDK dynamic proxy; Assigning a value to a business object enhancer enhancer = new enhancer (); Create a enhancer.setsuperclass to create a dynamic proxy class (This.target.getClass ()); Specifies the business class to be proxied for the actuator (that is, specify the parent class for the proxy class generated below)//Set callback: For calls to all methods on the proxy class, callback is called, and callback needs to implement the Intercept () method to block
Enhanc Er.setcallback (this);
//Create dynamic proxy class object and return
return Enhancer.create ();
}
//Implement callback method
public Object intercept (object obj, Method method, object[] args, methodproxy proxy) th Rows Throwable {
System.out.println ("preprocessing ——————");
Proxy.invokesuper (obj, args); Call the method of the business class (in the parent class)
System.out.println ("post-Invoke action ——————");
return null;
}
3: Create the Business class and proxy class object, and then pass the proxy class object. getinstance (The Business class object) returns a dynamic proxy class object (which is a subclass of the business class that can be pointed to by a business class reference). Finally, the method call is made through the dynamic proxy class object.
public static void Main (string[] args) { BookFacadeImpl1 bookfacade=new BookFacadeImpl1 (); bookfacadecglib cglib=new bookfacadecglib (); BOOKFACADEIMPL1 bookcglib= (BOOKFACADEIMPL1) cglib.getinstance (bookfacade); Bookcglib.addbook (); }
Four: Comparison
A static proxy is a proxy that explicitly defines a business implementation class in the code, wraps a business method with the same name in the proxy class, and invokes the wrapped business method through the proxy class;
The JDK dynamic agent invokes the same name method of the business implementation class in the dynamically generated proxy class through the method name in the interface;
Cglib Dynamic Proxy is a subclass of the business class, which is generated by inheriting the business class, and is represented by rewriting the business method;
Java Dynamic Agent's JDK implementation and CGLIB implementation