这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
整个机制的运转,可以分为相对独立的四个部分:业务应用编码使用spring-cloud-square相关的注解、bean的factory注册到spring环境、bean的factory类在spring环境实例化、通过factory的实例在spring生产HelloService接口的实现类
根据上面的分析,最重要的应该是bean的factory类:RetrofitClientFactoryBean,它实现了FactoryBean接口,其getObject方法就是根据HelloService接口生成实现类和关键,最终会调用下图红框中的Retrofit.create方法创建实例:
@Configuration @EnableRetrofitClients class OkHttpClientConfig{ @Bean @LoadBalanced public OkHttpClient.Builder okHttpClientBuilder() { return new OkHttpClient.Builder(); } }
@RetrofitClient("provider") public interface HelloService { @GET("/hello-obj") Call<HelloResponse> hello(@Query("name") String name); }
@RestController public class RemoteHello { @Autowired(required = false) HelloService helloService; @GetMapping("/remote-obj") public HelloResponse hello(@RequestParam("name") String name) throws IOException { return helloService.hello(name).execute().body(); } }
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import({ RetrofitConfiguration.class, RetrofitClientsRegistrar.class }) public @interface EnableRetrofitClients { String[] value() default {}; String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] defaultConfiguration() default {}; Class<?>[] clients() default {}; }
从上述代码可见RetrofitConfiguration和RetrofitClientsRegistrar都会比实例化,RetrofitConfiguration过于简单就不看了,重点关注RetrofitClientsRegistrar,先来看它的类图,搞清楚继承和实现
如下图所示,RetrofitClientsRegistrar集成自AbstractRetrofitClientsRegistrar,而AbstractRetrofitClientsRegistrar又集成自ImportBeanDefinitionRegistrar
所以,RetrofitClientsRegistrar被实例化的时候,就相当于ImportBeanDefinitionRegistrar接口的实现类被实例化了,这个ImportBeanDefinitionRegistrar接口,相信熟悉spring的同学对其不会陌生,它是用来动态注册bean的,那么接下来的重点就是ImportBeanDefinitionRegistrar的registerBeanDefinitions方法的具体内容,看看它到底注册了什么bean
registerBeanDefinitions方法的代码在AbstractRetrofitClientsRegistrar.java中(请在上面的类图中找到AbstractRetrofitClientsRegistrar的位置),如下所示,由于EnableRetrofitClients修饰的是咱们创建的OkHttpClientConfig.java,所以下面的入参AnnotationMetadata是OkHttpClientConfig类的注解信息:
@Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { registerDefaultConfiguration(metadata, registry); registerRetrofitClients(metadata, registry); }
上述代码的第一个方法registerDefaultConfiguration是注册配置信息的,非重点,跳过
上述代码的第二个方法registerRetrofitClients,这是本篇的关键,请重点关注下面代码中的中文注释:
public void registerRetrofitClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { ClassPathScanningCandidateComponentProvider scanner = getScanner(); scanner.setResourceLoader(this.resourceLoader); Set<String> basePackages; Map<String, Object> attrs = metadata.getAnnotationAttributes(getAnnotationClass().getName()); // 过滤条件:有RetrofitClient注解修饰的类,对应咱们代码中的HelloService.java AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(RetrofitClient.class); final Class<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients"); if (clients == null || clients.length == 0) { scanner.addIncludeFilter(annotationTypeFilter); basePackages = getBasePackages(metadata); } else { final Set<String> clientClasses = new HashSet<>(); basePackages = new HashSet<>(); for (Class<?> clazz : clients) { basePackages.add(ClassUtils.getPackageName(clazz)); clientClasses.add(clazz.getCanonicalName()); } AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() { @Override protected boolean match(ClassMetadata metadata) { String cleaned = metadata.getClassName().replaceAll("\\$", "."); return clientClasses.contains(cleaned); } }; scanner.addIncludeFilter(new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter))); } for (String basePackage : basePackages) { Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage); for (BeanDefinition candidateComponent : candidateComponents) { // 找到的结果就是HelloService接口 if (candidateComponent instanceof AnnotatedBeanDefinition) { // verify annotated class is an interface AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent; AnnotationMetadata annotationMetadata = beanDefinition.getMetadata(); Assert.isTrue(annotationMetadata.isInterface(), "@RetrofitClient can only be specified on an interface"); // 取得修饰HelloService类的RetrofitClient注解的所有属性 Map<String, Object> attributes = annotationMetadata .getAnnotationAttributes(RetrofitClient.class.getCanonicalName()); // 根据这些属性,得到远程访问的服务名是provider String name = getClientName(attributes); // 在spring注册一个配置类,名为provider.RetrofitClientSpecification, // 由于修饰HelloService的RetrofitClient注解并没有什么属性,所以这个配置类没有什么内容 registerClientConfiguration(registry, name, attributes.get("configuration")); // 这个方法要重点关注, // 入参annotationMetadata是HelloService的元信息, // attributes是修饰HelloService类的RetrofitClient注解的所有属性 registerRetrofitClient(registry, annotationMetadata, attributes); } } } }
private void registerRetrofitClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) { // 由于注解修饰的是HelloService类,所以这里className等于com.bolingcavalry.consumer.service.HelloService String className = annotationMetadata.getClassName(); // 注意getFactoryBeanClass()方法,来自RetrofitClientsRegistrar类,返回值是RetrofitClientFactoryBean.class, // 因此,RetrofitClientFactoryBean就被带入了definition中, // 注意,这个definition变量的类型是BeanDefinitionBuilder, // 其内部有个成员变量beanDefinition,此时该成员变量的beanClass字段已经被设置为RetrofitClientFactoryBean.class BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(getFactoryBeanClass()); validate(attributes); // HelloService的RetrofitClient注解没有设置url属性,因此这里是空字符串 definition.addPropertyValue("url", getUrl(attributes)); // RetrofitClient注解的value属性配置为远程服务名,这里是provider String name = getName(attributes); definition.addPropertyValue("name", name); // 类型就是HelloService definition.addPropertyValue("type", className); // by_type,意味着autowire注解修饰HelloService的时候,可以用HelloService获取对应的实现类 definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE); String alias = name + "RetrofitClient"; // 通过BeanDefinitionBuilder得到了beanDefinition, // 这个beanDefinition的beanClass字段在前面已经被设置为RetrofitClientFactoryBean.class AbstractBeanDefinition beanDefinition = definition.getBeanDefinition(); beanDefinition.setPrimary(true); String qualifier = getQualifier(attributes); if (StringUtils.hasText(qualifier)) { alias = qualifier; } // 将注册BeanDefinition所需的两个参数beanName和beanDefinition放入BeanDefinitionHolder对象中 BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[] { alias }); // 完成BeanDefinition在spring环境的注册,name等于com.bolingcavalry.consumer.service.HelloService,对应的BeanDefinition的beanClass等于RetrofitClientFactoryBean(注意,这很重要) BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry); }
在spring初始化过程中,上述红框中的代码会触发spring环境对HelloService接口实现类的实例化,完整的触发过程和详细堆栈就不细说了,这都是spring的标准处理流程,接下来会挑这里面的重点去看
首先就是大名鼎鼎的SpringApplication.refresh方法,这里面是bean的实例化逻辑,会执行一个重要方法,就是DefaultListableBeanFactory.doGetBeanNamesForType,这里面会遍历所有已注册的BeanDefinition,逐个处理,如下图:
doGetBean:256, AbstractBeanFactory (org.springframework.beans.factory.support) [2] getTypeForFactoryBean:1709, AbstractBeanFactory (org.springframework.beans.factory.support) getTypeForFactoryBean:899, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) isTypeMatch:637, AbstractBeanFactory (org.springframework.beans.factory.support) doGetBeanNamesForType:583, DefaultListableBeanFactory (org.springframework.beans.factory.support) getBeanNamesForType:542, DefaultListableBeanFactory (org.springframework.beans.factory.support) beanNamesForTypeIncludingAncestors:265, BeanFactoryUtils (org.springframework.beans.factory) findAutowireCandidates:1546, DefaultListableBeanFactory (org.springframework.beans.factory.support) doResolveDependency:1343, DefaultListableBeanFactory (org.springframework.beans.factory.support) resolveDependency:1300, DefaultListableBeanFactory (org.springframework.beans.factory.support) resolveAutowiredArgument:887, ConstructorResolver (org.springframework.beans.factory.support) createArgumentArray:791, ConstructorResolver (org.springframework.beans.factory.support) instantiateUsingFactoryMethod:541, ConstructorResolver (org.springframework.beans.factory.support) instantiateUsingFactoryMethod:1334, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) createBeanInstance:1177, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) doCreateBean:564, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) createBean:524, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support) getObject:-1, 1485624601 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$488) getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support) doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support) [1] getBean:213, AbstractBeanFactory (org.springframework.beans.factory.support) registerBeanPostProcessors:258, PostProcessorRegistrationDelegate (org.springframework.context.support) registerBeanPostProcessors:762, AbstractApplicationContext (org.springframework.context.support) refresh:567, AbstractApplicationContext (org.springframework.context.support) refresh:769, SpringApplication (org.springframework.boot) refresh:761, SpringApplication (org.springframework.boot) refreshContext:426, SpringApplication (org.springframework.boot) run:326, SpringApplication (org.springframework.boot) loadContext:123, SpringBootContextLoader (org.springframework.boot.test.context) loadContextInternal:99, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache) loadContext:124, DefaultCacheAwareContextLoaderDelegate (org.springframework.test.context.cache) getApplicationContext:124, DefaultTestContext (org.springframework.test.context.support) setUpRequestContextIfNecessary:190, ServletTestExecutionListener (org.springframework.test.context.web) prepareTestInstance:132, ServletTestExecutionListener (org.springframework.test.context.web) prepareTestInstance:244, TestContextManager (org.springframework.test.context) postProcessTestInstance:138, SpringExtension (org.springframework.test.context.junit.jupiter) lambda$invokeTestInstancePostProcessors$6:350, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) execute:-1, 2001115307 (org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$344) executeAndMaskThrowable:355, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) lambda$invokeTestInstancePostProcessors$7:350, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) accept:-1, 1650113431 (org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$343) accept:-1, 796667727 (java.util.stream.StreamSpliterators$WrappingSpliterator$$Lambda$107) accept:193, ReferencePipeline$3$1 (java.util.stream) accept:175, ReferencePipeline$2$1 (java.util.stream) forEachRemaining:1384, ArrayList$ArrayListSpliterator (java.util) copyInto:482, AbstractPipeline (java.util.stream) wrapAndCopyInto:472, AbstractPipeline (java.util.stream) forEachRemaining:312, StreamSpliterators$WrappingSpliterator (java.util.stream) forEachRemaining:743, Streams$ConcatSpliterator (java.util.stream) forEachRemaining:742, Streams$ConcatSpliterator (java.util.stream) forEach:580, ReferencePipeline$Head (java.util.stream) invokeTestInstancePostProcessors:349, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) lambda$instantiateAndPostProcessTestInstance$4:270, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) execute:-1, 1547883191 (org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$342) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) instantiateAndPostProcessTestInstance:269, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) lambda$testInstancesProvider$2:259, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) get:-1, 795748540 (org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$335) orElseGet:267, Optional (java.util) lambda$testInstancesProvider$3:258, ClassBasedTestDescriptor (org.junit.jupiter.engine.descriptor) getTestInstances:-1, 361398902 (org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor$$Lambda$234) getTestInstances:31, TestInstancesProvider (org.junit.jupiter.engine.execution) lambda$prepare$0:101, TestMethodTestDescriptor (org.junit.jupiter.engine.descriptor) execute:-1, 451312813 (org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor$$Lambda$334) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) prepare:100, TestMethodTestDescriptor (org.junit.jupiter.engine.descriptor) prepare:65, TestMethodTestDescriptor (org.junit.jupiter.engine.descriptor) lambda$prepare$1:111, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:-1, 1008315045 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$182) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) prepare:111, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:79, NodeTestTask (org.junit.platform.engine.support.hierarchical) accept:-1, 1976870338 (org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$201) forEach:1259, ArrayList (java.util) invokeAll:38, SameThreadHierarchicalTestExecutorService (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$5:143, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:-1, 1647809929 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$197) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$7:129, NodeTestTask (org.junit.platform.engine.support.hierarchical) invoke:-1, 928294079 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$196) around:137, Node (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$8:127, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:-1, 728885526 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$195) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) executeRecursively:126, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:84, NodeTestTask (org.junit.platform.engine.support.hierarchical) accept:-1, 1976870338 (org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService$$Lambda$201) forEach:1259, ArrayList (java.util) invokeAll:38, SameThreadHierarchicalTestExecutorService (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$5:143, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:-1, 1647809929 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$197) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$7:129, NodeTestTask (org.junit.platform.engine.support.hierarchical) invoke:-1, 928294079 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$196) around:137, Node (org.junit.platform.engine.support.hierarchical) lambda$executeRecursively$8:127, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:-1, 728885526 (org.junit.platform.engine.support.hierarchical.NodeTestTask$$Lambda$195) execute:73, ThrowableCollector (org.junit.platform.engine.support.hierarchical) executeRecursively:126, NodeTestTask (org.junit.platform.engine.support.hierarchical) execute:84, NodeTestTask (org.junit.platform.engine.support.hierarchical) submit:32, SameThreadHierarchicalTestExecutorService (org.junit.platform.engine.support.hierarchical) execute:57, HierarchicalTestExecutor (org.junit.platform.engine.support.hierarchical) execute:51, HierarchicalTestEngine (org.junit.platform.engine.support.hierarchical) execute:108, EngineExecutionOrchestrator (org.junit.platform.launcher.core) execute:88, EngineExecutionOrchestrator (org.junit.platform.launcher.core) lambda$execute$0:54, EngineExecutionOrchestrator (org.junit.platform.launcher.core) accept:-1, 607932305 (org.junit.platform.launcher.core.EngineExecutionOrchestrator$$Lambda$150) withInterceptedStreams:67, EngineExecutionOrchestrator (org.junit.platform.launcher.core) execute:52, EngineExecutionOrchestrator (org.junit.platform.launcher.core) execute:96, DefaultLauncher (org.junit.platform.launcher.core) execute:75, DefaultLauncher (org.junit.platform.launcher.core) startRunnerWithArgs:71, JUnit5IdeaTestRunner (com.intellij.junit5) startRunnerWithArgs:33, IdeaTestRunner$Repeater (com.intellij.rt.junit) prepareStreamsAndStart:221, JUnitStarter (com.intellij.rt.junit) main:54, JUnitStarter (com.intellij.rt.junit)
protected <T> T doGetBean( String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { // 入参name等于"com.bolingcavalry.consumer.service.HelloService" String beanName = transformedBeanName(name); Object beanInstance; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName); // sharedInstance等于null,因此下面的if判断不成立 if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // Fail if we're already creating this bean instance: // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); // parentBeanFactory等于null,因此下面的if判断不成立 if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { // Not found -> check parent. String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // typeCheckOnly等于true,因此下面的if判断不成立 if (!typeCheckOnly) { markBeanAsCreated(beanName); } StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate") .tag("beanName", name); try { if (requiredType != null) { beanCreation.tag("beanType", requiredType::toString); } // 前面咱们分析过,BeanDefinition已经注册到spring环境了, // 此处调用getMergedLocalBeanDefinition即可取得这个BeanDefinition RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); // HelloService的BeanDefinition没有依赖, // 因此dependsOn等于null,下面的if不成立 if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. // HelloService的bean是单例,因此下面的if判断成立 if (mbd.isSingleton()) { // 这里是创建bean的关键!!! // getSingleton传入一个lambda表达式,方法内会调用该表达式, sharedInstance = getSingleton(beanName, () -> { try { // 根据BeanDefinition创建bean, // 实际上执行的是AbstractAutowireCapableBeanFactory.createBean方法 return createBean(beanName, mbd, args); } catch (BeansException ex) { // Explicitly remove instance from singleton cache: It might have been put there // eagerly by the creation process, to allow for circular reference resolution. // Also remove any beans that received a temporary reference to the bean. destroySingleton(beanName); throw ex; } }); beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } else if (mbd.isPrototype()) { // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName); prototypeInstance = createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd); } else { String scopeName = mbd.getScope(); if (!StringUtils.hasLength(scopeName)) { throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'"); } Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new ScopeNotActiveException(beanName, scopeName, ex); } } } catch (BeansException ex) { beanCreation.tag("exception", ex.getClass().toString()); beanCreation.tag("message", String.valueOf(ex.getMessage())); cleanupAfterBeanCreationFailure(beanName); throw ex; } finally { beanCreation.end(); } } return adaptBeanInstance(name, beanInstance, requiredType); }
protected Object loadBalance(Retrofit.Builder builder, RetrofitContext context, String serviceIdUrl) { // 应用代码的OkHttpClientConfig.java中,okHttpClientBuilder方法生成了OkHttpClient.Builder实例,此处的instances中就是这个实例 Map<String, OkHttpClient.Builder> instances = context.getInstances(this.name, OkHttpClient.Builder.class); for (Map.Entry<String, OkHttpClient.Builder> entry : instances.entrySet()) { String beanName = entry.getKey(); OkHttpClient.Builder clientBuilder = entry.getValue(); // 应用代码的OkHttpClientConfig.java中,okHttpClientBuilder方法上已经用了LoadBalanced注解, //所以下面这个if判断为true if (applicationContext.findAnnotationOnBean(beanName, LoadBalanced.class) != null) { // 创建了OkHttpClient实例,传给了这个Retrofit.Builder builder.client(clientBuilder.build()); // 使用这个Retrofit.Builder去创建retrofit,相当于把上面创建的OkHttpClient实例带给了retrofit // 所以,这个retrofit实例的底层就是OkHttpClient Retrofit retrofit = buildAndSave(context, builder); // type的类型是HelloService, // retrofit.create就是要创建一个实例,该实例实现了HelloService接口 return retrofit.create(this.type); } } throw new IllegalStateException( "No Retrofit Client for loadBalancing defined. Did you forget to include spring-cloud-starter-square-okhttp?"); }
从上面的分析可见,咱们只写HelloService接口不写HelloService实现的关键就是retrofit.create方法,传入了一个接口定义,就能返回该接口的实现类的实例
说实话retrofit.create的源码并不属于spring-cloud-square,而是Retrofit自己的,在本文中看这段源码属于超纲,但我还是忍不住要看一下:
public <T> T create(final Class<T> service) { // 一些检查,例如service是不是接口 validateServiceInterface(service); return (T) // 这个实例是通过JDK的Proxy.newProxyInstance创建的 Proxy.newProxyInstance( service.getClassLoader(), new Class<?>[] {service}, new InvocationHandler() { private final Platform platform = Platform.get(); private final Object[] emptyArgs = new Object[0]; // 业务应用执行HelloService的hello方法时,实际上执行的是下面的方法 @Override public @Nullable Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable { // If the method is a method from Object then defer to normal invocation. if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } args = args != null ? args : emptyArgs; return platform.isDefaultMethod(method) ? platform.invokeDefaultMethod(method, service, proxy, args) : loadServiceMethod(method).invoke(args); } }); }
至此终于真像大白,最终还是用Proxy.newProxyInstance生成了HelloService的代理类实例,作为HelloService.hello调用背后的真正实现
最后似乎还有一点疑问,就是HelloService的RetrofitClient注解的属性是服务名provider,那么真正网络请求的时候,是如何转成真实的地址和端口的呢?
再回头看看咱应用consumer-retrofit-okhttp的pom.xml文件,如下图红框所示,和前文一样,这里也使用了spring-cloud-square-okhttp,而且咱们写的OkHttpClientConfig.java和前文也是一样的,所以,根据服务名获取地址和端口的操作依旧可以用前文的分析来解释:
欣宸还要再写一篇retrofit + webflux源码分析的文章?不不不,读源码太累,写出的文章,聪明的您读起来也累,所以就此打住吧
如果勤奋努力的您想独立阅读分析retrofit + webflux源码,这里给您一个建议,还记得本篇前面的那个类图吗,如下图,使用retrofit + webflux的时候,会用到spring-cloud-square-retrofit-webclient.jar,这个jar里面也有OkHttpClientConfig注解,它的import会实例化下图红框中的类,这个类就是您阅读源码的入口:
我是欣宸,期待与您一同畅游Java世界…
https://github.com/zq2599/blog_demos