欢送拜访我的GitHub

这里分类和汇总了欣宸的全副原创(含配套源码):https://github.com/zq2599/blog_demos

spring-cloud-square系列文章

  1. 五分钟搞懂spring-cloud-square
  2. spring-cloud-square开发实战(三种类型全笼罩)
  3. spring-cloud-square源码速读(spring-cloud-square-okhttp篇)
  4. spring-cloud-square源码速读(retrofit + okhttp篇)

本篇概览

  • 本文是《spring-cloud-square学习》系列的终篇,上一篇咱们理解了spring-cloud-square-okhttp库的源码和原理,明天晋升一点难度,看看spring-cloud-square的另一种类型的源码:<font color="blue">spring-cloud-square-retrofit</font>,也就是下图红框中的那种:

源码剖析指标

  • 接下来开始剖析spring-cloud-square-retrofit工程的源码,如下图红框所示:

  • 本篇指标十分明确,只搞清楚一件事:在应用spring-cloud-square的时候,以前文的consumer-retrofit-okhttp子工程为例,为什么咱们只写了HelloService接口,但却能通过Autowired注解应用HelloService的实现类?

提前小结

  • 如果您想理解spring-cloud-square的retrofit局部的原理,却又苦于没有工夫深入研究,能够看看上面这份提前小结的内容:
  1. 整个机制的运行,能够分为绝对独立的四个局部:业务利用编码应用spring-cloud-square相干的注解、bean的factory注册到spring环境、bean的factory类在spring环境实例化、通过factory的实例在spring生产HelloService接口的实现类
  2. 依据下面的剖析,最重要的应该是bean的factory类:<font color="blue">RetrofitClientFactoryBean</font>,它实现了FactoryBean接口,其getObject办法就是依据HelloService接口生成实现类和要害,最终会调用下图红框中的Retrofit.create办法创立实例:

  1. Retrofit类并非spring-cloud的我的项目,而是来自Retrofit库,其create办法中应用了JDK的Proxy.newProxyInstance办法,该办法能够依据HelloService接口生成一个实现了该接口的实例:

  1. 在应用spring-cloud-square的retrofit + okhttp计划时,HelloService接口中应用的还是近程服务的服务名,而不是地址和端口,这是因为应用了spring-cloud-square-okhttp库,所以服务名转为<font color="red">地址+端口</font>的逻辑与前文《spring-cloud-square源码速读(spring-cloud-square-okhttp篇)》保持一致
  • 以上就是整个源码剖析的论断了,我将波及到的关联代码流程整顿成简图,如下所示:

回顾利用如何应用spring-cloud-square-retrofit

  • 在剖析源码之前,先回顾一下《spring-cloud-square开发实战》中的代码,咱们过后是如何应用<font color="blue">spring-cloud-square-retrofit</font>的(对应demo中的consumer-retrofit-okhttp子工程)
  1. 新建配置类OkHttpClientConfig,应用了EnableRetrofitClients注解,向spring环境注册OkHttpClient.Builder实例:
@Configuration@EnableRetrofitClientsclass OkHttpClientConfig{    @Bean    @LoadBalanced    public OkHttpClient.Builder okHttpClientBuilder() {        return new OkHttpClient.Builder();    }}
  1. 定义HelloService接口,用注解RetrofitClient润饰,注解的值是近程调用的服务名<font color="blue"></font>,外面申明hello办法,用注解GET润饰,注解的值是近程调用的接口的path:
@RetrofitClient("provider")public interface HelloService {    @GET("/hello-obj")    Call<HelloResponse> hello(@Query("name") String name);}
  1. 在业务要做近程调用的时候,用Autowired注解润饰HelloService接口,即可调用HelloService.hello办法,至于接口对应的实例来自哪里,开发者不用关注:
@RestControllerpublic 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();    }}
  • 以上就是咱们开发业务代码时应用spring-cloud-square的要害操作,接下来就从源码角度来剖析这些操作到底施展了什么作用

源码剖析(类定义注册阶段)

  • 回顾一下咱们写的OkHttpClientConfig.java,外面应用了注解<font color="blue">EnableRetrofitClients</font>,这就是本次浏览代码的入口:
@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);                }            }        }    }
  • 将上述代码中最初调用的registerRetrofitClient办法开展如下,这段代码做了件很重要的事件:注册BeanDefinition到spring,注册的name等于<font color="blue">com.bolingcavalry.consumer.service.HelloService</font>,对应的BeanDefinition的beanClass等于<font color="red">RetrofitClientFactoryBean</font>:
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);    }
  • 此刻,HelloService的类定义曾经在spring实现了注册,接下来要看HelloService接口的实现类来自何处;

BeanDefinition中的RetrofitClientFactoryBean被实例化

  • 在spring初始化过程中,上述红框中的代码会触发spring环境对HelloService接口实现类的实例化,残缺的触发过程和具体堆栈就不细说了,这都是spring的规范解决流程,接下来会挑这外面的重点去看
  • 首先就是赫赫有名的SpringApplication.refresh办法,这外面是bean的实例化逻辑,会执行一个重要办法,就是DefaultListableBeanFactory.doGetBeanNamesForType,这外面会遍历所有已注册的BeanDefinition,一一解决,如下图:

  • DefaultListableBeanFactory.doGetBeanNamesForType继续执行,会到下一个重点:依据BeanDefinition创立bean,堆栈如下,这是用条件断点失去的:
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)
  • 根据上述堆栈,要细看AbstractBeanFactory的doGetBean办法,请关注中文正文:
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);    }
  • 至此,RetrofitClientFactoryBean曾经实现了实例化,接下来要去看HelloService接口背地的bean是怎么创立的

HelloService对应的bean是如何创立的

  • 回顾一下,咱们的利用代码中用到HelloService的场景,如下图红框所示,应用Autowired注解润饰HelloService:

  • 首先,上图中的RemoteHello是肯定会创立bean的,在创立的过程中,DefaultListableBeanFactory.doResolveDependency办法负责解决RemoteHello依赖的bean,如下图所示,在此处触发了HelloService的bean的实例化

  • 辗转反侧,再次走到了AbstractBeanFactory.doGetBean办法,这次会执行下图第二个红框中的getObjectForBeanInstance办法:

  • 而后到了最要害的地位:AbstractBeanFactory.getObjectForBeanInstance办法,这外面将RetrofitClientFactoryBean当做factory用了,用来生产HelloService:

  • 将上图红框2中的getObjectFromFactoryBean办法持续开展,进入FactoryBeanRegistrySupport.doGetObjectFromFactoryBean办法,这里实现了从spring框架到利用自定义之间的过渡:将bean的创立交给利用本人注册的Factory来解决:

  • 在RetrofitClientFactoryBean.getObject中,执行loadBalance(builder, context, serviceIdUrl):

  • loadBalance的实现在RetrofitClientFactoryBean中:
    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和前文也是一样的,所以,依据服务名获取地址和端口的操作仍旧能够用前文的剖析来解释:

  • 至于HelloService.hello办法,如何对应到web申请,请容我说一声:这是retrofit和okhttp之间的事件,在这里算是超纲了,篇幅所限,切实展不开了...

尾记:对于另一种spring-cloud-square类型:retrofit + webflux

  • 之前的文章曾经剖析过,spring-cloud-square一共有三种类型,如下图所示,两个绿框中的源码都剖析过了,还剩下的只有红色的<font color="blue">retrofit + webflux</font>组合:

  • 欣宸还要再写一篇<font color="blue">retrofit + webflux</font>源码剖析的文章?不不不,读源码太累,写出的文章,聪慧的您读起来也累,所以就此打住吧
  • 如果勤奋努力的您想独立浏览剖析<font color="blue">retrofit + webflux</font>源码,这里给您一个倡议,还记得本篇后面的那个类图吗,如下图,应用<font color="blue">retrofit + webflux</font>的时候,会用到spring-cloud-square-retrofit-webclient.jar,这个jar外面也有OkHttpClientConfig注解,它的import会实例化下图红框中的类,这个类就是您浏览源码的入口:

  • 至此《spring-cloud-square学习》系列曾经全副实现,心愿这四篇文章能够帮忙您全面把握spring-cloud-square,在您的我的项目中对近程调用的操作更加得心应手;

你不孤独,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢送关注公众号:程序员欣宸

微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游Java世界...

https://github.com/zq2599/blog_demos