SpringBoot自动装配原理、条件注解及封装Starter
创始人
2024-05-29 09:57:27
0

1.什么是 SpringBoot 自动装配?

我们现在提到自动装配的时候,一般会和Spring Boot联系在一起。但是实际上SpringFramework 早就实现了这个功能。Spring Boot 只是在其基础上,通过 SPI 的方式,做了进一步优化。
SpringBoot 定义了一套接口规范:
SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。
没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。

     org.springframework.boot    spring-boot-starter-data-redis 
 

引入 starter 之后,我们通过少量注解和一些简单的配置就能使用第三方组件提供的功能了。

2.SpringBoot 是如何实现自动装配的?

依赖SpringBoot的核心注解实现 @SpringBootApplication

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {xxxx
}

其中@EnableAutoConfiguration 是实现自动装配的重要注解,我们以这个注解入手。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
xxx
}

可以看到自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector
那我们继续分析下AutoConfigurationImportSelector 类到底做了什么?
在这里插入图片描述

AutoConfigurationImportSelector:加载自动装配类

可以看到他是实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中。

public String[] selectImports(AnnotationMetadata annotationMetadata) {// 判断自动装配开关是否打开 默认是开启if (!this.isEnabled(annotationMetadata)) {return NO_IMPORTS;}// 获取获取所有需要装配的beanAutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());}

我们在继续看getAutoConfigurationEntry 方法是如何获取装配bean的

/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;
}
// 获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 获取装配Bean
List configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 过滤重复bean
configurations = removeDuplicates(configurations);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
// 移除需要排除的bean
configurations.removeAll(exclusions);
// 根据AutoConfigurationImportFilter的match方法来判断是否符合OnBeanCondition,OnClassCondition,OnWebApplicationCondition 过滤bean
configurations = getConfigurationClassFilter().filter(configurations);
// 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}

其中getCandidateConfigurationsgetConfigurationClassFilter().filter 方法为核心
getCandidateConfigurations 获取配置bean ,如图所示
在这里插入图片描述
主要调用 org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames
再调用 org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories如图所示
其原理就是读取META-INF/spring.factories文件的的URL
在这里插入图片描述
getConfigurationClassFilter().filter 方法用于根据AutoConfigurationImportFilter的match方法来判断是否符合OnBeanCondition,OnClassCondition,OnWebApplicationCondition 过滤bean 如图所示
在这里插入图片描述
最后,总结下SpringBoot自动配置的原理,主要做了以下事情:

  1. spring.factories配置文件中加载自动配置类,利用org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories 方法实现
  2. 加载的自动配置类中排除掉@EnableAutoConfiguration注解的exclude属性指定的自动配置类;
  3. 再用AutoConfigurationImportFilter接口去过滤自动配置类是否符合其标注注解
    OnBeanCondition(如:ConditionalOnBean、ConditionalOnMissingBean)、OnClassCondition(如:ConditionalOnClass、ConditionalOnMissingClass)、OnWebApplicationCondition(如ConditionalOnWebApplication、ConditionalOnNotWebApplication)的条件,若都符合的话则返回匹配结果;
  4. 触发AutoConfigurationImportEvent事件
  5. 最后spring再将最后筛选后的自动配置类导入IOC容器中

拓展
1.条件注解
@ConditionalOnBean:当容器里有指定 Bean 的条件下
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选 Bean
@ConditionalOnClass:当类路径下有指定类的条件下
@ConditionalOnMissingClass:当类路径下没有指定类的条件下
@ConditionalOnProperty:指定的属性是否有指定的值
@ConditionalOnResource:类路径是否有指定的值
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件
@ConditionalOnJava:基于 Java 版本作为判断条件
@ConditionalOnJndi:在 JNDI 存在的条件下差在指定的位置
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下
@ConditionalOnWebApplication:当前项目是 Web 项 目的条件下
2.控制自动装配顺序注解
@AutoConfigureOrder
@AutoConfigureBefore
@AutoConfigureAfter
@AutoConfiguration(after = xx.class, before = xx.class)
@AutoConfigureOrder 此需要制定自定配置的顺序时,可以用 @AutoConfigureOrder ,表示绝对顺序(数字越小,优先顺序越高)。
@AutoConfigureBefore@AutoConfigureAfter 控制应用配置类的相对顺序。
具体顺序如下:

  1. 根据类名按照字母表递增排序
  2. 根据 @AutoConfigureOrder value 值(默认:0)递增排序
  3. 根据 @AutoConfigureBefore@AutoConfigureAfter 调整排序
    AutoConfigurationSorter 类是具体实现排序的逻辑

3.Starter编写

在这里插入图片描述在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...