AOP proxy analysis and aop proxy
I. Proxy
The proxy class and the target class implement the same interface and the same method.
If you use the factory mode and configuration file for management, you do not need to modify the client program. In the configuration file, configure the target class or the proxy class, so that it is easy to switch. (For example, implementation of the Spring framework)
AOP: the goal of AOP is to modularize the cross-business and move the aspect code to the scope of the original method.
Ii. Dynamic proxy
The JVM can dynamically generate class bytecode during runtime. This dynamically generated class is often used as a proxy class, that is, a dynamic proxy class.
The dynamic class generated by JVM must implement one or more interfaces. Therefore, the dynamic class generated by JVM can only be used as a proxy for the target class with the same interface.
The CGLIB library can dynamically generate a subclass of a class, and a subclass of a class can also be used as a proxy for this class. Therefore, if you want to generate a dynamic proxy class for a class without interfaces, you can use the CGLIB library.
3. In each method of the proxy class, in addition to the corresponding method of the target and the structure returned by the external return target, you can also add the system function code in four locations of the proxy method.
1. Before calling the target method
2. After calling the target method
3. Before and after calling the target method
4. In the catch Block that handles the exception of the target method
4. Test the dynamic proxy class generated by JVM in code.
// Create a jvm dynamic proxy and view all constructors and parameter types (the original class is Collection)
Class clazzProxy = Proxy. getProxyClass (Collection. class. getClassLoader (), Collection. class); // obtain the byte code of the proxy object // obtain all Constructor constructors = clazzProxy of the dynamic proxy class. getConstructors (); for (Constructor constructor: constructors) {String name = constructor. getName (); StringBuilder sbuilder = new StringBuilder (name); sbuilder. append ("{"); // obtain all the parameter types of the constructor Class [] clazzParames = constructor. getParameterTypes (); For (Class clazzParame: clazzParames) {// concatenate the parameter type into sbuilder. append (clazzParame. getName (). append (",");} if (clazzParames! = Null & clazzParames. length! =-1) {sbuilder. deleteCharAt (sbuilder. length ()-1);} sbuilder. append ("}"); System. out. println (sbuilder );
// Create a jvm dynamic proxy and view all methods and parameter types (the original class is Collection)
Method [] methods = clazzProxy. getMethods (); for (Method constructor: methods) {String name = constructor. getName (); StringBuilder sbuilder = new StringBuilder (name); sbuilder. append ("{"); // obtain all the parameter types of the method. Class [] clazzParames = constructor. getParameterTypes (); for (Class clazzParame: clazzParames) {// concatenate the parameter types into sbuilder. append (clazzParame. getName ()). append (",");} if (clazzParames! = Null & clazzParames. length! =-1) {sbuilder. deleteCharAt (sbuilder. length ()-1);} sbuilder. append ("}"); System. out. println (sbuilder );
// Method 1 for creating an instantiated object for a dynamic class (the original class is Collection)
Constructor constructor = clazzProxy. getConstructor (InvocationHandler. class); // You must create a constructor with parameters. // InvocationHandler is an interface. You must create a class to implement the class MyInvocationHandler1 implements InvocationHandler {@ Overridepublic Object invoke (Object proxy, method method, Object [] args) throws Throwable {return null;} // creates an Object and transmits the Collection collectonProxy1 = (Collection) constructor Object that implements the InvocationHandler class. newInstance (new MyInvocationHandler1 (); System. out. println (collectonProxy1); // The output is null // The toString () method of the dynamic proxy object is null
// Method 2 (the original class is Collection) to create an instantiated object for a dynamic class --- create an anonymous internal class
Collection collectionProxy2 = (Collection) constructor.newInstance(new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {return null;}});
// Method 3 for creating an instantiated object for a dynamic class --- directly put in place in one step // pass 3 parameters, and the second parameter is the interface array type
Collection collectionProxy3 = (Collection) Proxy. newProxyInstance (Collection. class. getClassLoader (), new Class [] {Collection. class}, new InvocationHandler () {ArrayList target = new ArrayList ();//!!! Change the ArrayList object to a member variable. Each call is the same proxy object @ Override // proxy: represents the proxy object method: represents the method called by the proxy object args: public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {Object retVal = method. invoke (target, args );
// Reflection mechanism, call the target method of the target object ///// pass it to the target targetSystem. out. println (method. getName () + "called .. "); // The return object will be returned to the proxy. Return retVal ;}} can be filtered out. // The object call method is tested. // The InvocationHandler class invoke () is executed every time the add () method is called () method collectionProxy3.add ("wzl"); collectionProxy3.add ("hlw"); // The returned value of the method of the called proxy object is System from the return value of invoke. out. println (collectionProxy3.size ());
//-----------------------------------------------------------------------------
// Extract to method, and the InvocationHandler class transmits two objects (the target object and the object encapsulated by the system function method)
1. System Method Interface
/** System function interface class */public interface Advice {void beforMethod (); // system function method before the target method (only the target method is passed, target, method, and args parameter can be passed. void afterMethod (Method method); // system function method after the target Method}
2. system method class implementing the Interface Class
/** Class implementing System function interfaces */public class MyAdvice implements Advice {private long startTime = 0; @ Overridepublic void beforMethod () {System. out. println ("---- System method before calling the target method"); startTime = System. currentTimeMillis () ;}@ Overridepublic void afterMethod (Method method) {System. out. println ("---- System method after the target method is called"); long endTime = System. currentTimeMillis (); System. out. println (method. getName () + "execution time:" + (endTime-startTime ));}}
3. Extract as a method. The InvocationHandler class passes two objects (the original class is Collection) --- (the object encapsulated by the target object and System Function Method)
// 1. Create the target object targetfinal ArrayList target = new ArrayList ();//!!! Change the ArrayList object to a member variable. Each call is a Collection of the same proxy object collectionProxy4 = (Collection) getProxy (target, new MyAdvice ()); // transfer the target object and objects that implement system functions/* test collectionProxy4.add ("wzl"); collectionProxy4.add ("hlw "); // The returned value of the method of the called proxy object is System from the return value of invoke. out. println (collectionProxy4.size (); * // InvocationHandler class transfers two objects: private static Object getProxy (final Object target, final Advice advice) {return (Object) Proxy. newProxyIns Tance (target. getClass (). getClassLoader (), // implements the same class loader as the target object. getClass (). getInterfaces (), // implements the same interface as the target object. new InvocationHandler () {@ Override // proxy: represents the proxy object method: represents the method called by the proxy object args: public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {advice. beforMethod (); Object retVal = method. invoke (target, args); // reflection mechanism, call the method advice of the target object. afterMethod (method );//// // Pass to the target // return object will be returned to the proxy. Return retVal ;}});}