【橘子SpringCloud】OpenFegin源码分析

1. Feign配置流程

1.1 Feign相关注解说明

1.1.1 @EnableFeignClients 注解

扫描声明为feign客户端的接口( 通过 @FeignClient 注解),配置组件扫描指令用于与 @Configuration 一起使用。

org.springframework.cloud.openfeign.EnableFeignClients

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
   
   

    /**
     * basePackages属性的别名,允许更灵活的写法;
     * 如 @ComponentScan("org.my.pkg"),而不是写为 @ComponentScan(basePackages="org.my.pkg")
     * 
     * @return 返回basePackages的字符串数组。
     */
    String[] value() default {
   
   };

    /**
     * 注解组件扫描的基础包。
     * value属性是该属性的别名。
     * 类型安全的变体是使用basePackageClasses()属性,直接指定Class,而不是使用基于字符串的包名。
     * @return 返回basePackages字符串数组。
     */
    String[] basePackages() default {
   
   };

    /**
     * basePackages()属性类型安全的变体,直接使用Class对象数组指定要扫描的注解组件所在的包。
     * 该属性设置的每个Class所在的包都扫描。
     * 推荐在每个需要扫描的包中创建一个特殊的没有任何操作的标记类或接口,仅仅用于设置需要扫描的包。
     * @return 返回basePackageClasses的Class数组。
     */
    Class<?>[] basePackageClasses() default {
   
   };

    /**
     * 为所有feign客户端指定的自定义的@Configuration。
     * 可以覆盖@Bean定义中组成feign客户端的组件设置,如Decoder、Encoder、Contract等。
     * @return 默认配置的Class数组。
     */
    Class<?>[] defaultConfiguration() default {
   
   };

    /**
     * 使用@FeignClient注解的类的Class数组。如果非空,则禁用类路径扫描。
     * @return list of FeignClient classes
     */
    Class<?>[] clients() default {
   
   };

}
1.1.2 @FeignClient 注解

业务接口使用该注解标记之后,该业务接口的实现类对象基于feign客户端实现,是一个代理对象。

如果Spring Cloud的LoadBalancer可用,就使用Spring Cloud的LoadBalancer对后端的请求进行负载均衡。

org.springframework.cloud.openfeign.FeignClient

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface FeignClient {
   
   

    /**
     * 服务的名称,具有可选的协议前缀。name的同义词。
     * 无论客户端是否指定了url,都必须配置name属性值。
     * 同时该属性的值中可以包含SpEL表达式,如${propertyKey}。
     * @return 返回带有可选协议前缀的服务name值。
     */
    @AliasFor("name")
    String value() default "";

    /**
     * 该属性的值作为bean的名称,而不是作为name属性值,但是不作为服务的ID。
     * @return 返回bean的名称而不是name属性的值。
     */
    String contextId() default "";

    /**
     * @return 返回带有可选协议前缀的服务id,value的同义词。
     */
    @AliasFor("value")
    String name() default "";

    /**
     * @return 返回feign客户端的@Qualifiers值。
     */
    String[] qualifiers() default {
   
   };

    /**
     * @return 返回绝对的URL或可解析的hostname(协议是可选的)。
     */
    String url() default "";

    /**
     * @return 404错误是否应该解析而不是抛异常FeignExceptions。默认false表示抛异常。
     */
    boolean dismiss404() default false;

    /**
     * feign客户端的自定义配置类。
     * 在该配置中可以覆盖构建feign客户端用到的@Bean定义,如Decoder、Encoder以及Contract。
     * @return 返回feign客户端的配置类列表。
     */
    Class<?>[] configuration() default {
   
   };

    /**
     * 指定feign客户端接口的服务降级类。该服务降级类必须实现@FeignClient标记的接口;
     * 同时服务降级类必须是一个spring bean。
     * @return 返回指定feign客户端接口的服务降级类。
     */
    Class<?> fallback() default void.class;

    /**
     * 为指定的feign客户端接口定义服务降级工厂。
     * 服务降级工厂生产的服务降级实例必须实现@FeignClient标记的接口。
     * 同时服务降级工厂必须是一个spring bean。
     * @return 返回指定feign客户端接口的服务降级工厂Class对象。
     */
    Class<?> fallbackFactory() default void.class;

    /**
     * 返回所有方法级别映射的路径前缀。
     */
    String path() default "";

    /**
     * 返回:是否将feign代理对象标记为首选bean,默认true。
     */
    boolean primary() default true;

}

1.2. Feign涉及到的配置类

1.2.1 feign注解的处理

org.springframework.cloud.openfeign.FeignAutoConfiguration.DefaultFeignTargeterConfiguration

@Configuration(proxyBeanMethods = false)
@Conditional(FeignCircuitBreakerDisabledConditions.class)
protected static class DefaultFeignTargeterConfiguration {
   
   

    @Bean
    @ConditionalOnMissingBean
    public Targeter feignTargeter() {
   
   
       return new DefaultTargeter();
    }

}

在配置中,将targeter添加到上下文中。

org.springframework.cloud.openfeign.DefaultTargeter

class DefaultTargeter implements Targeter {
   
   

    @Override
    public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignClientFactory context,
          Target.HardCodedTarget<T> target) {
   
   
       return feign.target(target);
    }

}

默认的Targeter实现中,target方法的执行如下:

  • 直接调用feign的target方法创建业务接口代理对象的实例。

1.3. feign注解的处理流程

1.3.1 主入口方法

org.example.openfeign.demo.BizApplication#main

public static void main(String[] args) {
   
   
    SpringApplication.run(BizApplication.class, args);
}
1.3.2 SpringApplication的run方法

org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String…)

public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
   
   
    return run(new Class<?>[] {
   
    primarySource }, args);
}
1.3.3 SpringApplication重载的run方法

静态帮助类,可用于从指定的资源使用默认的设置以及用户提供的参数运行一个SpringApplication。

传递的参数:

  • primarySource:优先加载的资源;
  • args:应用参数,通常是从java的main方法传递进来的;

返回值:

  • 返回运行中的ApplicationContext对象。

org.springframework.boot.SpringApplication#run(java.lang.Class<?>[], java.lang.String[])

public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
   
   
    return new SpringApplication(primarySources).run(args);
}
1.3.4 SpringApplication重载的run方法

运行Spring应用,创建并刷新一个新的ApplicationContext对象。

传递的参数:

  • args:应用参数,通常是从java的main方法传递进来的;

返回值:

  • 返回运行中的ApplicationContext对象。

org.springframework.boot.SpringApplication#run(java.lang.String…)

public ConfigurableApplicationContext run(String... args) {
   
   
    // 记录当前时间
    long startTime = System.nanoTime();
    // 创建Bootstrap上下文
    DefaultBootstrapContext bootstrapContext = createBootstrapContext();
    ConfigurableApplicationContext context = null;
    // 配置无头属性值
    configureHeadlessProperty();
    // 根据传递的参数获取Spring应用运行的监听器集合
    SpringApplicationRunListeners listeners = getRunListeners(args);
    // 开始监听
    listeners.starting(bootstrapContext, this.mainApplicationClass);
    try {
   
   
        // 创建默认的应用参数对象,封装传递的应用参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // 准备环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
        // 打印banner
        Banner printedBanner = printBanner(environment);
        // 创建应用上下文
        context = createApplicationContext();
        context.setApplicationStartup(this.applicationStartup);
        // 准备上下文
        prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
        // 刷新上下文
        refreshContext(context);
        // 应用上下文刷新后处理
        afterRefresh(context, applicationArguments);
        Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
        if (this.logStartupInfo) {
   
   
        	new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
        }
        // 调用监听器的started方法,通知应用上下文已经启动了。
        listeners.started(context, timeTakenToStartup);
        // 调用runners
        callRunners(context, applicationArguments);
    } catch (Throwable ex) {
   
   
        if (ex instanceof AbandonedRunException) {
   
   
            throw ex;
        }
        handleRunFailure(context, ex, listeners);
        throw new IllegalStateException(ex);
    }
    
    try {
   
   
        if (context.isRunning()) {
   
   
            Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
            // runners执行结束后,标记上下文已经准备好。
            listeners.ready(context, timeTakenToReady);
        }
    } catch (Throwable ex) {
   
   
        if (ex instanceof AbandonedRunException) {
   
   
        	throw ex;
        }
        handleRunFailure(context, ex, null);
        throw new IllegalStateException(ex);
    }
    // 返回运行中的应用上下文
    return context;
}
1.3.5 SpringApplication的刷新上下文

org.springframework.boot.SpringApplication#refreshContext

private void refreshContext(ConfigurableApplicationContext context) {
   
   
    if (this.registerShutdownHook) {
   
   
       shutdownHook.registerApplicationContext(context);
    }
    // 调用refresh方法刷新指定的应用上下文
    refresh(context);
}
1.3.6 SpringApplication的 refresh 方法

调用应用上下文的refresh方法刷新上下文。

org.springframework.boot.SpringApplication#refresh

protected void refresh(ConfigurableApplicationContext applicationContext) {
   
   
    applicationContext.refresh();
}
1.3.7 ServletWebServerApplicationContext的refresh方法

上下文刷新的方法

org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#refresh

@Override
public final void refresh() throws BeansException, IllegalStateException {
   
   
    try {
   
   
        // 调用父类的方法执行上下文的刷新
    	super.refresh();
    } catch (RuntimeException ex) {
   
   
        WebServer webServer = this.webServer;
        if (webServer != null) {
   
   
        	webServer.stop();
        }
        throw ex;
    }
}
1.3.8 抽象应用上下文的刷新方法

执行抽象应用上下文中的刷新方法。

org.springframework.context.support.AbstractApplicationContext#refresh

@Override
public void refresh() throws BeansException, IllegalStateException {
   
   
    synchronized (this.startupShutdownMonitor) {
   
   
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 1. 准备刷新
        prepareRefresh();

        // 2. 通知子类刷新内部bean工厂。
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 3. 准备当前上下文中用到的bean工厂。
        prepareBeanFactory(beanFactory);

        try {
   
   
            // 4. 允许上下文子类中的bean工厂的后处理。
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");

            // 5. 调用注册到上下文中的工厂处理器。
            invokeBeanFactoryPostProcessors(beanFactory);

            // 6. 注册拦截bean创建的bean处理器。
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // 7. 初始化当前上下文中用到的消息源。
            initMessageSource();

            // 8. 初始化当前上下文中的事件多播。
            initApplicationEventMulticaster();

            // 9. 初始化特定子类上下文中的其他指定的bean。
            onRefresh();

            // 10. 检查监听器bean并注册。
            registerListeners();

            // 11. 初始化剩余的非懒初始化的单例bean。
            finishBeanFactoryInitialization(beanFactory);

            // 12. 最后,发布对应的事件。
            finishRefresh();
        } catch (BeansException ex) {
   
   
            if (logger.isWarnEnabled()) {
   
   
                logger.warn("Exception encountered during context initialization - " +
                    "cancelling refresh attempt: " + ex);
            }
            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();
            // Reset 'active' flag.
            cancelRefresh(ex);
            // Propagate exception to caller.
            throw ex;
        } finally {
   
   
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
            contextRefresh.end();
        }
    }
}
1.3.9 抽象应用上下文的调用bean工厂后处理器方法

实例化并调所有注册的BeanFactoryPostProcessor bean,如果显式指定了顺序就按照指定的顺序调用。

必须在单例实例化之前调用。

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
   
   
    
    // 使用后处理注册表代理调用bean工厂后处理器
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null &&
    		beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
   
   
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}
1.3.10 抽象应用上下文的调用bean工厂后处理器的重载方法

抽象应用上下文中的调用bean工厂后处理器的方法。

org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
       ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
   
   

    // 如果有的话,先调用BeanDefinitionRegistryPostProcessors。
    Set<String> processedBeans = new HashSet<>();

    // 如果bean工厂是BeanDefinitionRegistry类型
    if (beanFactory instanceof BeanDefinitionRegistry registry) {
   
   
        // 新建普通后处理器集合
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
   
   
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor registryProcessor) {
   
   
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            } else {
   
   
                regularPostProcessors.add(postProcessor);
            }
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // 1. 首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors。
        String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
   
   
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
   
   
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(
            currentRegistryProcessors, registry, beanFactory.getApplicationStartup()
        );
        currentRegistryProcessors.clear();

        // 2. 然后,调用实现了Ordered接口的BeanDefinitionRegistryPostProcessors。
        postProcessorNames = beanFactory.getBeanNamesForType(
            BeanDefinitionRegistryPostProcessor.class,
            true,
            false
        );
        for (String ppName : postProcessorNames) {
   
   
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
   
   
                currentRegistryProcessors.add(
                    beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)
                );
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(
            currentRegistryProcessors,
            registry,
            beanFactory.getApplicationStartup()
        );
        currentRegistryProcessors.clear();
        // 3. 最后,调用调用其余的BeanDefinitionRegistryPostProcessors。
        boolean reiterate = true;
        while (reiterate) {
   
   
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(
                BeanDefinitionRegistryPostProcessor.class,
                true,
                false
            );
            for (String ppName : postProcessorNames) {
   
   
                if (!processedBeans.contains(ppName)) {
   
   
                    currentRegistryProcessors.add(
                        beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)
                    );
                    
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(
                currentRegistryProcessors, registry, beanFactory.getApplicationStartup()
            );

            currentRegistryProcessors.clear();
        }

        // 4. 现在,对所有已经处理过的所有处理器,调用它们的postProcessBeanFactory回调。
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    } else {
   
   
        // 否则,调用使用上下文实例注册的工厂处理器。
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    String[] postProcessorNames = beanFactory.getBeanNamesForType(
        BeanFactoryPostProcessor.class,
        true,
        false
    );

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
   
   
        if (processedBeans.contains(ppName)) {
   
   
            // skip - already processed in first phase above
        } else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
   
   
            priorityOrderedPostProcessors.add(
                beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)
            );
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
   
   
            orderedPostProcessorNames.add(ppName);
        } else {
   
   
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
   
   
    	orderedPostProcessors.add(
            beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)
        );
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
   
   
    	nonOrderedPostProcessors.add(
            beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)
        );
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}
1.3.11 后处理器注册表代理的调用bean定义注册中心处理器的方法

调用指定的BeanDefinitionRegistryPostProcessor beans。

org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanDefinitionRegistryPostProcessors

private static void invokeBeanDefinitionRegistryPostProcessors(
        Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors,
        BeanDefinitionRegistry registry,
        ApplicationStartup applicationStartup) {
   
   

    // 遍历后处理器集合
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
   
   
        StartupStep postProcessBeanDefRegistry = applicationStartup.start(
            "spring.context.beandef-registry.post-process"
        ).tag("postProcessor", postProcessor::toString);
        
        // 调用处理器的bean定义注册中心的后处理方法进行处理
        postProcessor.postProcessBeanDefinitionRegistry(registry);
        // 后处理结束
        postProcessBeanDefRegistry.end();
    }
}
1.3.12 bean定义注册表的后处理

从注册中心的配置类中导出更多的bean定义。

org.springframework.context.annotation.ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   
   
    int registryId = System.identityHashCode(registry);
    
    // 如果已经处理过了,则抛异常
    if (this.registriesPostProcessed.contains(registryId)) {
   
   
        throw new IllegalStateException(
        	"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
    }
	// 如果已经处理过了,则抛异常
    if (this.factoriesPostProcessed.contains(registryId)) {
   
   
        throw new IllegalStateException(
        	"postProcessBeanFactory already called on this post-processor against " + registry);
    }
    // 将注册中心id添加到已处理集合中
    this.registriesPostProcessed.add(registryId);
	// 处理注册中心配置类的bean定义
    processConfigBeanDefinitions(registry);
}
1.3.13 处理配置类的bean定义

基于 Configuration 类的注册中心构建并验证配置模型。

org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
   
   
    // 新建bean定义持有对象的列表集合
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    // 从注册中心获取bean定义的名称集合
    String[] candidateNames = registry.getBeanDefinitionNames();
	
    // 遍历名称集合
    for (String beanName : candidateNames) {
   
   
        // 从注册中心获取当前bean名称对应的bean定义
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        
        // 如果bean定义中CONFIGURATION_CLASS_ATTRIBUTE对应的属性不是null,则记录日志
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
   
   
            if (logger.isDebugEnabled()) {
   
   
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
   
   
            // 否则,如果配置类通过了校验,则创建新的bean定义持有对象,添加到bean定义持有对象集合中。
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // 如果没有找到 @Configuration 类,则方法立即返回。
    if (configCandidates.isEmpty()) {
   
   
    	return;
    }

    // 对配置类持有对象中包含的bean定义的order值执行数值排序
    configCandidates.sort((bd1, bd2) -> {
   
   
        // 获取order值
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        // 获取order值
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        // 返回比较的结果
        return Integer.compare(i1, i2);
    });
    
    // 检测通过嵌套的应用上下文提供的用户自定义bean名称生成策略。
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry _sbr) {
   
   
        sbr = _sbr;
        if (!this.localBeanNameGeneratorSet) {
   
   
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR
            );
            if (generator != null) {
   
   
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
    	}
    }
    
	// 如果环境为null,则创建标准环境对象并赋值
    if (this.environment == null) {
   
   
    	this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory,
        this.problemReporter,
        this.environment,
        this.resourceLoader,
        this.componentScanBeanNameGenerator,
        registry
    );

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
   
   
        StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
        parser.parse(candidates);
        parser.validate();

        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
   
   
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry,
                this.sourceExtractor,
                this.resourceLoader,
                this.environment,
                this.importBeanNameGenerator,
                parser.getImportRegistry()
            );
        }
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
   
   
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = Set.of(candidateNames);
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
   
   
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
   
   
                if (!oldCandidateNames.contains(candidateName)) {
   
   
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                            bd,
                            this.metadataReaderFactory)
                            && !alreadyParsedClasses.contains(bd.getBeanClassName())) {
   
   
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    } while (!candidates.isEmpty());

    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
   
   
    	sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    // Store the PropertySourceDescriptors to contribute them Ahead-of-time if necessary
    this.propertySourceDescriptors = parser.getPropertySourceDescriptors();

    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory cachingMetadataReaderFactory) {
   
   
        // Clear cache in externally provided MetadataReaderFactory; this is a no-op
        // for a shared cache since it'll be cleared by the ApplicationContext.
        cachingMetadataReaderFactory.clearCache();
    }
}
1.3.14 加载bean定义

读取 configurationModel,使用基于其内容的注册中心执行bean定义的注册。

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitions

public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
   
   
    TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
    // 遍历配置模型中的配置类
    for (ConfigurationClass configClass : configurationModel) {
   
   
        // 从配置类中加载bean定义
		loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
    }
}
1.3.15 为配置类加载bean定义

读取指定的 ConfigurationClass 注册该bean,同时对其内部包含的 @Bean 注解的方法返回值进行bean定义的注册。

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass

private void loadBeanDefinitionsForConfigurationClass(
       ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
   
   
	
    // 如果配置类应该跳过,则
    if (trackedConditionEvaluator.shouldSkip(configClass)) {
   
   
        String beanName = configClass.getBeanName();
        // 如果beanName不为空并且注册中心包含该名称的bean定义,则从注册中心移除该bean的定义。
        if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
   
   
            this.registry.removeBeanDefinition(beanName);
        }
        // 引入的注册中心移除引入的bean定义。
        this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        // 方法返回
        return;
    }
    
	// 如果配置类是引入的
    if (configClass.isImported()) {
   
   
        // 对引入的配置类执行bean定义的注册
    	registerBeanDefinitionForImportedConfigurationClass(configClass);
    }
    // 获取配置类中所有添加了 @Bean 注解的方法,遍历
    for (BeanMethod beanMethod : configClass.getBeanMethods()) {
   
   
        // 从 @Bean 注解的方法加载bean的定义
    	loadBeanDefinitionsForBeanMethod(beanMethod);
    }
	// 从引入的配置类中引入的资源中加载bean定义
    loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
    // 从引入的配置类的引入的bean定义注册中心加载bean的定义
    loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}
1.3.16 从注册表加载bean定义

调用 regsiterBeanDefinitions 方法执行bean定义的注册。

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsFromRegistrars

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   
   
    // 遍历registrars集合,调用registrar的注册bean定义方法执行bean定义的注册
    registrars.forEach((registrar, metadata) ->
		// 调用registerBeanDefinitions方法执行bean定义的注册。
		registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator)
	);
}
1.3.17 注册bean定义

基于引入的@Configuration类注册bean的定义。

注意:由于与@Configuration类处理的声明周期限制,BeanDefinitionRegistryPostProcessor类型可能不会在这里注册。

默认实现将bean定义的注册代理给 registerBeanDefinitions(AnnotationMetadata, BeanDefinitionRegistry) 方法。

传递的参数:

  • importingClassMetadata:引入类的注解元数据;

  • registry:当前bean定义注册中心;

  • importBeanNameGenerator:引入的bean的名称生成器,默认使用 ConfigurationClassPostProcessor.IMPORT_BEAN_NAME_GENERATOR,如果用户通过 ConfigurationClassPostProcessor.setBeanNameGenerator 设置了命名规则,则使用用户指定的命名规则。

    对于用户指定的命名规则,同样用于所在的应用上下文的组件扫描,否则默认使用 AnnotationBeanNameGenerator.INSTANCE 执行组件扫描。

org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.beans.factory.support.BeanNameGenerator)

default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
       BeanNameGenerator importBeanNameGenerator) {
   
   
	// 注册bean定义
    registerBeanDefinitions(importingClassMetadata, registry);
}
1.3.18 注册bean定义

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerBeanDefinitions

// 注册bean定义
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
   
    // 注册默认的配置
    registerDefaultConfiguration(metadata, registry);
    // 注册feign客户端
    registerFeignClients(metadata, registry);
}
1.3.18.1 注册默认配置

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerDefaultConfiguration

// 注册默认的配置
private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
   

    // 获取EnableFeignClients注解的属性集合
    Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);

    // 如果存在,并且提供了defaultConfiguration配置
    if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
   
   
        String name;
        if (metadata.hasEnclosingClass()) {
   
   
            name = "default." + metadata.getEnclosingClassName();
        } else {
   
   
            name = "default." + metadata.getClassName();
        }
        // 注册客户端配置
        registerClientConfiguration(registry, name, "default", defaultAttrs.get("defaultConfiguration"));
    }
}
1.3.18.2 注册客户端配置

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerClientConfiguration

private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object className,
       Object configuration) {
   
   
    // 获取FeignClientSpecification类型的bean定义建造器
    BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
    // 添加构造器参数值
    builder.addConstructorArgValue(name);
    // 添加构造器参数值
    builder.addConstructorArgValue(className);
    // 添加构造器参数值
    builder.addConstructorArgValue(configuration);
    // 注册bean定义,名称为"<name>.FeignClientSpecification"
    registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(),
          builder.getBeanDefinition());
}
1.3.19 @EnableFeignClients 注解的处理

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClients

// 注册feign客户端
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
   
   

    LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();

    // 从元数据中获取EnableFeignClients注解的属性值集合
    Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());

    // 获取EnableFeignClients注解中clients的属性值
    final Class<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients");

    // 如果clients为null或长度为0
    if (clients == null || clients.length == 0) {
   
   
        // 获取类路径组件扫描器
        ClassPathScanningCandidateComponentProvider scanner = getScanner();
        // 设置资源加载器
        scanner.setResourceLoader(this.resourceLoader);
        // 添加包含过滤器:扫描添加了@FeignClient注解的类
        scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
        // 获取根路径
        Set<String> basePackages = getBasePackages(metadata);
        // 遍历根路径
        for (String basePackage : basePackages) {
   
   
            // 通过扫描器扫描指定根路径下的添加了@FeignClient注解的接口,并添加到candidateComponents集合中
            candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
        }
    } else {
   
   
        // 如果设置了EnableFeignClients注解的clients属性值,则遍历属性值的元素
        for (Class<?> clazz : clients) {
   
   
            // 将添加了@FeignClient注解的Class对象封装后添加到candidateComponents集合中。
            candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
        }
    }

    // 遍历candidateComponents
    for (BeanDefinition candidateComponent : candidateComponents) {
   
   
        // 如果是基于注解的bean定义
        if (candidateComponent instanceof AnnotatedBeanDefinition beanDefinition) {
   
   
            // verify annotated class is an interface
            // 获取bean定义的元数据
            AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
            Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");

            // 从元数据中获取FeignClient的属性值集合
            Map<String, Object> attributes = annotationMetadata
                .getAnnotationAttributes(FeignClient.class.getCanonicalName());
            // 获取客户端name属性值
            String name = getClientName(attributes);
            // 获取类名
            String className = annotationMetadata.getClassName();
            // 注册客户端配置
            registerClientConfiguration(registry, name, className, attributes.get("configuration"));
            // 注册feign客户端
            registerFeignClient(registry, annotationMetadata, attributes);
        }
    }
}
1.3.20 注册feign客户端

org.springframework.cloud.openfeign.FeignClientsRegistrar#registerFeignClient

// 注册feign客户端
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata,
        Map<String, Object> attributes) {
   
   
    // 从注解元数据中获取类名
    String className = annotationMetadata.getClassName();
    // 如果禁用属性的懒解析,则立即注册feign客户端的bean定义
    if (String.valueOf(false).equals(
            environment.getProperty("spring.cloud.openfeign.lazy-attributes-resolution", String.valueOf(false)))) {
   
   
        eagerlyRegisterFeignClientBeanDefinition(className, attributes, registry);
    } else {
   
   
        // 延迟注册feign客户端bean定义
        lazilyRegisterFeignClientBeanDefinition(className, attributes, registry);
    }
}
1.3.21 @FeignClient 注解的处理

org.springframework.cloud.openfeign.FeignClientsRegistrar#eagerlyRegisterFeignClientBeanDefinition

private void eagerlyRegisterFeignClientBeanDefinition(String className, Map<String, Object> attributes,
        BeanDefinitionRegistry registry) {
   
   
    validate(attributes);
    // 获取FeignClientFactoryBean类型的bean定义
    BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
    // 设置url属性值为从客户端配置属性中获取到的url的值,如果注解中没有配置,则设置为null值;
    definition.addPropertyValue
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值