Original address
https://blog.csdn.net/rokii/article/details/4046098
Dynamic Proxy is actually a java.lang.reflect.Proxy class that dynamically generates a class byte according to all the interfaces you specify. This class will inherit the Proxy class and implement all the interfaces you specify (the interface array you pass in the parameters); Then use the classloader you specify to load the class byte into the system. Finally, generate an object of such a class and initialize some values of the object, such as invocationHandler, that is, the Method members corresponding to all interfaces. After initialization, the object is returned to the calling client. In this way, the client gets a Proxy object that implements all your interfaces. See example analysis:
I. business interface class
public interface BusinessProcessor { public void processBusiness(); }
II. Business realization
public class BusinessProcessorImpl implements BusinessProcessor { public void processBusiness() { System.out.println("processing business....."); } }
III. business agent
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class BusinessProcessorHandler implements InvocationHandler { private Object target = null; public BusinessProcessorHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("You can do something here before process your business"); Object result = method.invoke(target, args); System.out.println("You can do something here after process your business"); return result; } }
Four client applications
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; public class Test { public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); } }
Now let's look at the print results:
You can do something here before process your business processing business..... You can do something here after process your business
Through the results, we can easily see the role of Proxy. It can do some auxiliary work you want to do before and after your core business methods, such as log, security mechanism and so on.
Now let's analyze the working principle of the above class.
Class one or two has nothing to say. Let's look at class three first. Implements the invoke method of the InvocationHandler interface. In fact, this class is the fixed interface method called by the final proxy. Proxy does not care how the client's business methods are implemented. When the client calls proxy, it will only call the invoke interface of InvocationHandler, so our real implemented method must be called in the invoke method. The relationship is as follows:
BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....); bp.processBusiness()-->invocationHandler.invoke()-->bpimpl.processBusiness();
So what kind of object is bp. Let's change the main method to see:
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); }
Output results:
You can do something here before process your business processing business..... You can do something here after process your business $Proxy0
bp was originally an object of $Proxy0. So what does this class look like? well. Let's write two more methods to print this class to see what it is? We write the following two static methods under main.
public static String getModifier(int modifier){ String result = ""; switch(modifier){ case Modifier.PRIVATE: result = "private"; case Modifier.PUBLIC: result = "public"; case Modifier.PROTECTED: result = "protected"; case Modifier.ABSTRACT : result = "abstract"; case Modifier.FINAL : result = "final"; case Modifier.NATIVE : result = "native"; case Modifier.STATIC : result = "static"; case Modifier.SYNCHRONIZED : result = "synchronized"; case Modifier.STRICT : result = "strict"; case Modifier.TRANSIENT : result = "transient"; case Modifier.VOLATILE : result = "volatile"; case Modifier.INTERFACE : result = "interface"; } return result; } public static void printClassDefinition(Class clz){ String clzModifier = getModifier(clz.getModifiers()); if(clzModifier!=null && !clzModifier.equals("")){ clzModifier = clzModifier + " "; } String superClz = clz.getSuperclass().getName(); if(superClz!=null && !superClz.equals("")){ superClz = "extends " + superClz; } Class[] interfaces = clz.getInterfaces(); String inters = ""; for(int i=0; i<interfaces.length; i++){ if(i==0){ inters += "implements "; } inters += interfaces[i].getName(); } System.out.println(clzModifier +clz.getName()+" " + superClz +" " + inters ); System.out.println("{"); Field[] fields = clz.getDeclaredFields(); for(int i=0; i<fields.length; i++){ String modifier = getModifier(fields[i].getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String fieldName = fields[i].getName(); String fieldType = fields[i].getType().getName(); System.out.println(" "+modifier + fieldType + " "+ fieldName + ";"); } System.out.println(); Method[] methods = clz.getDeclaredMethods(); for(int i=0; i<methods.length; i++){ Method method = methods[i]; String modifier = getModifier(method.getModifiers()); if(modifier!=null && !modifier.equals("")){ modifier = modifier + " "; } String methodName = method.getName(); Class returnClz = method.getReturnType(); String retrunType = returnClz.getName(); Class[] clzs = method.getParameterTypes(); String paraList = "("; for(int j=0; j<clzs.length; j++){ paraList += clzs[j].getName(); if(j != clzs.length -1 ){ paraList += ", "; } } paraList += ")"; clzs = method.getExceptionTypes(); String exceptions = ""; for(int j=0; j<clzs.length; j++){ if(j==0){ exceptions += "throws "; } exceptions += clzs[j].getName(); if(j != clzs.length -1 ){ exceptions += ", "; } } exceptions += ";"; String methodPrototype = modifier +retrunType+" "+methodName+paraList+exceptions; System.out.println(" "+methodPrototype ); } System.out.println("}"); }
Then rewrite the main method
public static void main(String[] args) { BusinessProcessorImpl bpimpl = new BusinessProcessorImpl(); BusinessProcessorHandler handler = new BusinessProcessorHandler(bpimpl); BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler); bp.processBusiness(); System.out.println(bp.getClass().getName()); Class clz = bp.getClass(); printClassDefinition(clz); }
Now let's look at the output:
You can do something here before process your business processing business..... You can do something here after process your business $Proxy0 $Proxy0 extends java.lang.reflect.Proxy implements com.tom.proxy.dynamic.BusinessProcessor { java.lang.reflect.Method m4; java.lang.reflect.Method m2; java.lang.reflect.Method m0; java.lang.reflect.Method m3; java.lang.reflect.Method m1; void processBusiness(); int hashCode(); boolean equals(java.lang.Object); java.lang.String toString(); }
Obviously, the Proxy.newProxyInstance method will do the following:
-
Dynamically generate a class according to the second parameter interfaces passed in to implement the interface in interfaces. In this example, the processBusiness method of the BusinessProcessor interface. It also inherits the Proxy class and overrides three methods: hashcode, toString and equals. See ProxyGenerator.generateProxyClass(...) for specific implementation; The $Proxy0 class is generated in this example
-
Load the newly generated class into the jvm through the first parameter classloder passed in. About to load $Proxy0 class
-
With the third argument, call P r o x y 0 of Proxy0 The Proxy0(InvocationHandler) constructor of Proxy0 creates an object of $Proxy0, traverses the methods of all its interfaces with the interfaces parameter, and generates a Method object to initialize several Method member variables of the object
-
Return an instance of $Proxy0 to the client.
It's alright now. We'll see how the client adjusts.
-
What the client gets is P r o x y 0 of real example yes as , from to Instance object of Proxy0 due to The instance object of Proxy0. Since Proxy0 inherits BusinessProcessor, there is no problem in converting it into BusinessProcessor.
BusinessProcessor bp = (BusinessProcessor)Proxy.newProxyInstance(....); -
bp.processBusiness();
What is actually called is P r o x y 0. p r o c e s s B u s i n e s s ( ) ; that Do you Proxy0.processBusiness(); that Proxy0.processBusiness(); Then the implementation of proxy0. Processbusiness () is to call the invoke method through InvocationHandler!