这些不知道,别说你熟悉 Spring( 二 )


这些不知道,别说你熟悉 Spring

文章插图
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 。
这些不知道,别说你熟悉 Spring

文章插图
主要方法为 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); }方法解读
  1. 通过 spring.boot.enableautoconfiguration 配置项判断是否启用自动装配,默认为 true
  2. 使用上述说的 SpringFactoriesLoader.loadFactoryNames() 加载所有 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的实现类的全限定类名,借助 HashSet 进行去重
  3. 获取 @EnableAutoConfiguration 注解上配置的要 exclude 的类,然后排除这些特定类
  4. 通过 @ConditionalOnXXX 进行过滤,满足条件的类才会留下,封装到 AutoConfigurationEntry 里返回
那 getAutoConfigurationEntry() 方法在哪儿调用呢?
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(); }

经验总结扩展阅读