写点什么

【源码系列】Spring Boot 自动装配

用户头像
Alex🐒
关注
发布于: 2021 年 06 月 09 日

Spring Boot 源码:自动装配

核心注解和接口

@EnableAutoConfiguration

@EnableAutoConfiguration public @interface SpringBootApplication {     }
复制代码

@EnableXXX

Spring 3.1.x 开始支持各种 @Enable 注解,作用:把相关组件的 Bean 装配到 IoC 容器,减少代码配置和使用难度。


@Import 是 @Enable 注解的核心,Spring 会解析 @Import 参数,来实现 Bean 的装配

@Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {      Class<?>[] exclude() default {};      String[] excludeName() default {}; }
复制代码

AutoConfigurationImportSelector

public class AutoConfigurationImportSelector    implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,    BeanFactoryAware, EnvironmentAware, Ordered { }
复制代码


ImportSelector

方法表示返回的参数(String[])就是要装配到 IoC 容器的类,**可以实现批量装配,**可以在方式实现中进行更灵活复杂的装配逻辑

public interface ImportSelector {      String[] selectImports(AnnotationMetadata importingClassMetadata); }
复制代码


AutoConfigurationImportSelector 的实现

@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {      AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader       .loadMetadata(this.beanClassLoader);      AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(       autoConfigurationMetadata, annotationMetadata);        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}
protected AutoConfigurationEntry getAutoConfigurationEntry( AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) { // 获取 exclude\excludeName AnnotationAttributes attributes = getAttributes(annotationMetadata); // 获取所有自动装配的配置类 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); // 去除重复配置 configurations = removeDuplicates(configurations); // 去除exclude配置 Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); // 广播装配事件 fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions);}
复制代码


获取所有自动装配的配置类

使用到 SpringFactoriesLoader,扫描 classpath 下的 META-INF/spring.factories 文件

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,  AnnotationAttributes attributes) {     List<String> configurations = SpringFactoriesLoader.loadFactoryNames(       getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());     return configurations;}
复制代码


META-INF/spring.factories 文件内容是 KEY=VALUE 格式

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.netflix.eureka.config.EurekaClientConfigServerAutoConfiguration,\ org.springframework.cloud.netflix.eureka.config.EurekaDiscoveryClientConfigServiceAutoConfiguration,\ org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration,\ org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,\ org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration 
org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\ xxxx.xxxxx.xxxListener,\ xxxx.xxxxx.xxxListener,\ xxxx.xxxxx.xxxListener,\
复制代码


loadFactoryNames() 方法根据 KEY 得到 VALUE 值 XXXXConfiguration,就是基于 JavaConfig 的配置类,可以看到很多条件注解

@Configuration @ConditionalOnProperty(  value = {"eureka.client.enabled"},  matchIfMissing = true ) @ConditionalOnDiscoveryEnabled public class EurekaClientAutoConfiguration { }
复制代码


广播装配事件

private void fireAutoConfigurationImportEvents(List<String> configurations,  Set<String> exclusions) {      // 再次用到 SpringFactoriesLoader,获取所有 AutoConfigurationImportListener 实现类,并广播事件     List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();     if (!listeners.isEmpty()) {      AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,        configurations, exclusions);      for (AutoConfigurationImportListener listener : listeners) {       invokeAwareMethods(listener);       listener.onAutoConfigurationImportEvent(event);      }     }}
protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() { return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class, this.beanClassLoader);}
复制代码


发布于: 2021 年 06 月 09 日阅读数: 11
用户头像

Alex🐒

关注

还未添加个人签名 2020.04.30 加入

还未添加个人简介

评论

发布
暂无评论
【源码系列】Spring Boot 自动装配