An abstract interface, a functional class, and a proxy class of a functional class. Agent classes combine functional classes. Both functional classes and proxies of functional classes implement abstract interfaces. The caller calls the actual function class through the proxy class.
Agents are divided into static agents and dynamic agents. Classic use of dynamic proxy: Retrofitopen source library.
1. The difference from the adapter mode: the adapter mode mainly changes the interface of the object under consideration, while the proxy mode cannot change the interface of the proxy class. 2. The difference between the decorator mode and the decorator mode: the decorator mode is to enhance the function, while the proxy mode is to control it.
Customize an interface interface. Dynamic proxies can only proxy interfaces, because the proxy class inherits the Proxy class.
Customize Handlerclasses, extend implementation InvocationHandlerinterfaces, and implement invokemethods.
By Proxy.newProxyInstanceobtaining a dynamic proxy class instance proxy. The first parameter is the classLoader of the interface, the second parameter is the class of the interface, and the third parameter is the object instance of step 2.
proxyIt implements the interface interface, and you can call the interface method. At this time, the method of calling the interface will eventually call the method InvocationHandlerin step 2 invoke.
Roles in dynamic proxies
interface is an abstract interface in the proxy pattern.
InvocationHandlerIs the role of the actual functional class (RealClass) in the proxy pattern.
Proxy.newProxyInstanceInside the function, a proxy class will be generated in the JVM, that is, the proxy class ProxyClass in the proxy mode; the function return result is an instance object of the proxy class, which is equivalent to the one in the client proxyClassObject.
Get the Proxy proxy class.
getProxyClass(ClassLoader loader, Class<?>... interfaces)Get the proxy class class type. You can use this class type to reflect the constructor and create an instance.
newProxyInstance method analysis
Generate proxy class. getProxyClass0Generate proxy classes through methods. This function can generate a $Proxy0.classfile and load it into the JVM as a proxy class.
Obtain the proxy class constructor through reflection. The input parameters of the constructor are InvocationHandler.
Generate proxy class instances through the constructor.
publicstaticObjectnewProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throwsIllegalArgumentException{
Objects.requireNonNull(h);finalClass<?>[] intfs = interfaces.clone();// 省略....../*
* Look up or generate the designated proxy class.
*/Class<?> cl =getProxyClass0(loader, intfs);// 步骤1。核心步骤,生成class类,并让JVM加载。/*
* Invoke its constructor with the designated invocation handler.
*/try{
// 省略......finalConstructor<?> cons = cl.getConstructor(constructorParams);// 步骤2 获取构造函数finalInvocationHandler ih = h;if(!Modifier.isPublic(cl.getModifiers())){
cons.setAccessible(true);}return cons.newInstance(newObject[]{
h});// 步骤3 new 一个代理类实例}catch(IllegalAccessException|InstantiationException e){
thrownewInternalError(e.toString(), e);}catch(InvocationTargetException e){
// 省略......}catch(NoSuchMethodException e){
thrownewInternalError(e.toString(), e);}}
Implementation of getProxyClass0 function in standard JVM virtual machine
The core implementation of generating dynamic classes is Proxy.ProxyClassFactory#applymethods. Call ProxyGenerator.generateProxyClass(final String name, Class<?>[] interfaces, int accessFlags)method.
generateProxyClassThe principle is probably to parse the methods defined in the interface, and then $Proxy0.classgenerate a class file through character splicing or writing a file (file name), load it into the JVM, and generate a proxy class.
Proxy class generated by the system. The code below $Proxy0is not actually decompiled from the dynamic proxy class file generated by jvm, but refers to other bloggers' articles and roughly wrote it to facilitate understanding of the proxy class generated by the system.
Implementation of getProxyClass0 function in Android virtual machine
Core implementation: The core implementation of generating dynamic classes is Proxy.ProxyClassFactory#applymethods. Call the native method Proxy#generateProxyto generate a proxy class.
/**
* A factory function that generates, defines and returns the proxy class given
* the ClassLoader and array of interfaces.
*/privatestaticfinalclassProxyClassFactoryimplementsBiFunction<ClassLoader,Class<?>[],Class<?>>{
// prefix for all proxy class namesprivatestaticfinalString proxyClassNamePrefix ="$Proxy";// next number to use for generation of unique proxy class namesprivatestaticfinalAtomicLong nextUniqueNumber =newAtomicLong();@OverridepublicClass<?>apply(ClassLoader loader,Class<?>[] interfaces){
//省略部分代码..... for循环校验interfaces 合法性//省略部分代码..... for循环遍历非public的接口类,确保所有非public接口是同包名下的{
// Android-changed: Generate the proxy directly instead of calling// through to ProxyGenerator.List<Method> methods =getMethods(interfaces);Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);validateReturnTypes(methods);List<Class<?>[]> exceptions =deduplicateAndGetExceptions(methods);Method[] methodsArray = methods.toArray(newMethod[methods.size()]);Class<?>[][] exceptionsArray = exceptions.toArray(newClass<?>[exceptions.size()][]);/*
* Choose a name for the proxy class to generate.
*/long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num;//包名 + 类名 + 数字returngenerateProxy(proxyName, interfaces, loader, methodsArray, exceptionsArray);}}}
Function flow: Proxy#getProxyClass0-> WeakCache#get-> WeakCache.Factory#Factory-> WeakCache.Factory#get-> Proxy.ProxyClassFactory#apply-> Proxy#generateProxy-> native methodProxy_generateProxy
WeakCache#subKeyFactoryThe type is Proxy.KeyFactory; WeakCache#valueFactorythe type is Proxy.ProxyClassFactory; WeakCache.Factoryinherited function.Supplier;
// java.lang.reflect.Proxy/**
* a cache of proxy classes
*/privatestaticfinalWeakCache<ClassLoader,Class<?>[],Class<?>>
proxyClassCache =newWeakCache<>(newKeyFactory(),newProxyClassFactory());
generateProxyNative implements Android system source code: art/runtime/native/java_lang_reflect_Proxy.cc
As defined in the art/runtime/class_linker.cc source code file ClassLinker::CreateProxyClass, this method is the core method for Android to generate class proxy classes.