
文章插图
SpringBoot 核心要点上面讲的 SPI 其实就是我们 SpringBoot 自动装配的核心 。
何为自动装配?
自动装配对应的就是手动装配,在没 SpringBoot 之前,我们使用 Spring 就是用的手动装配模式 。在使用某项第三方功能时,我们需要引入该功能依赖的所有包,并测试保证这些引入包版本兼容 。然后在 XML 文件里进行大量标签配置,非常繁琐 。后来 Spring4 里引入了 JavaConfig 功能,利用 @Configuration + @Bean 来代替 XML 配置,虽然对开发来说是友好了许多,但是这些模板式配置代码还是很繁琐,会浪费大量时间做配置 。Java 重可能也就是这个时候给人留的一种印象 。
在该背景下出现了 SpringBoot,SpringBoot 可以说是稳住了 Java 的地位 。SpringBoot 提供了自动装配功能,自动装配简单来说就是将某种功能(如 web 相关、redis 相关、logging 相关等)打包在一起,统一管理依赖包版本,并且约定好相关功能 Bean 的装配规则,使用者只需引入一个依赖,通过少量注解或简单配置就可以使用第三方组件提供的功能了 。
在 SpringBoot 中这类功能组件有一个好听的名字叫做 starter 。比如 spring-boot-starter-web、spring-boot-starter-data-redis、spring-boot-starter-logging 等 。starter 里会通过 @Configuration + @Bean + @ConditionalOnXXX 等注解定义要注入 Spring 中的 Bean,然后在 spring.factories 文件中配置为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的实现,就可以完成自动装配了 。
具体装配流程怎么样的呢?
其实也很简单,基本都是 Spring 中的知识,没啥新颖的 。主要依托于@EnableAutoConfiguration 注解,该注解上会 Import 一个 AutoConfigurationImportSelector,看下继承关系,该类继承于 DeferredImportSelector 。

文章插图
主要方法为 getAutoConfigurationEntry()
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {// 1if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY;}AnnotationAttributes attributes = getAttributes(annotationMetadata);// 2List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);configurations = removeDuplicates(configurations);// 3Set<String> exclusions = getExclusions(annotationMetadata, attributes);checkExcludedClasses(configurations, exclusions);configurations.removeAll(exclusions);// 4configurations = getConfigurationClassFilter().filter(configurations);fireAutoConfigurationImportEvents(configurations, exclusions);return new AutoConfigurationEntry(configurations, exclusions); }方法解读- 通过 spring.boot.enableautoconfiguration 配置项判断是否启用自动装配,默认为 true
- 使用上述说的 SpringFactoriesLoader.loadFactoryNames() 加载所有 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的实现类的全限定类名,借助 HashSet 进行去重
- 获取 @EnableAutoConfiguration 注解上配置的要 exclude 的类,然后排除这些特定类
- 通过 @ConditionalOnXXX 进行过滤,满足条件的类才会留下,封装到 AutoConfigurationEntry 里返回
public void refresh() throws BeansException, IllegalStateException {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh(); }
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 年纪大了,这些星座就喜欢看甜甜的恋爱
- 胸闷是什么感觉
- 虽然单身时花心,但这些星座一旦恋爱就十分专一
- 主动创造激情,这些星座的爱越来越有深度
- 跟前任碰到,这些星座会落落大方
- 哪些星座男在恋爱中吵架,永远不知道错哪了
- 重燃爱火,这些星座配对有可能分手后还会和好
- 爱情的阴沟里不知道翻了多少次船的星座
- 剑盾如何联网
- 爱情早已戒掉,这些星座只想做自己的王者
