Spring Boot自动配置原理
上篇Spring Boot基本配置之入口类和@SpringBootApplication已经查看到了Spring Boot启动时自动装配了哪些内容,那么Spring Boot是如何知晓装配内容并在启动时自动加载的呢?答案尽在@SpringBootApplication注解。
Spring Boot自动配置机制从核心上可以总结为以下两点:
1、通过@EnableAutoConfiguration为基于Spring的应用开启自动配置机制;
2、通过一系列的@Conditional完成自动配置机制的实现,关于Spring的条件注解可参考Spring Boot 热插拔技术应用 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)。
如何理解自动配置?自动配置即根据开发者添加的jar包依赖,会自动将一些配置类的bean注册到ioc容器内。使用时只需方便的添加@Autowire或者@Resource等注解即可使用。
通过源码可知其为组合注解
@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解各个分析:
一、@SpringBootConfiguration
通过源码分析:@SpringBootConfiguration等价于@Configuration,其为@Configuration的重新封装命名同时默认使用代理bean方法。
二、@EnableAutoConfiguration
对于此注解,标记可覆盖属性为“spring.boot.enableautoconfiguration”,同时与如下两注解作用:
1、@AutoConfigurationPackage
@Import这个注解,使用Spring经常可见,其为spring底层注解,表示给容器中导入一个组件。此处导入的组件是Registrar.class。那Registrar组件的功能是什么呢?查看源码如下:
通过Registrar源码,可知其主要干一件事,注册一个bean。那么这个bean是什么呢?我们跟踪调试查看下:
这个bean就是
其中的packageNames为,即main主函数所在包。
综合此注解功能就是自动装配main主函数所在package中所有bean。
2、@Import({AutoConfigurationImportSelector.class})
此处导入容器的组件是AutoConfigurationImportSelector.class,关于这个enable注解的原理可参考Spring高级特性之三:@Enable*注解的工作原理
,其UML图如下:
对于*Aware相关的接口,其为Spring提供的Bean与Spring框架耦合的契机。简单说就是Spring的一个亮点就是开发者使用Bean对Spring容器的存在是没有意识的,可以将使用的容器替换成其他的容器。但实际应用中有时不可避免的要用到Spring容器本身的功能资源,这个时候Bean必须意识其所在容器的存在才能调用Spring提供的而相关资源。这个功能可以通过Spring Aware。具体可参考Spring高级特性之一: Aware之ApplicationContextAware。
AutoConfiurationImportSelector类实现了图中的相关Aware,重点是此类实现了DeferredImportSelector接口的getImportGroup()方法:
下面分析自动装配的主要逻辑process的功能:
依次跟踪调试可以发现EnableAutoConfigurationImportSelector使用SpringFactoriesLoader:loadFactoryNames方法扫描spring.factorires文件
此文件声明哪些需要自动配置。打开该文件
打开上面任意配置文件,如:
可以明确看到很多@ConditionalXXX相关的条件注解:
其实这个实现逻辑可以参考Dubbo SPI机制之一JDK中的SPI进行对比。以上的自动装配都是Spring Boot嵌入的,下面以http编码为例简析一个自定义的配置如何自动装配:
常规项目配置http编码实在web.xml文件中配置一个filter避免中文乱码,如:
如果将上述过程改为自动装配,那必须满足两个条件:
1)能配置CharacterEncodingFilter这个Bean;
2)能配置encoding和forceEncoding这两个参数。
首先,关于配置参数。之前分析过类型安全配置(参考Spring Boot外部配置属性注入),Spring Boot参数配置基于此实现。这个配置类可以在application.properties中直接设置,如下:
那么参数对应源码应该是
对于其他可在application.properties中设置参数的选项,其参数配置源码,应该都是类似的XXXProperties并包含注@ConfigurationProperties("XXX")。
其次,对于注册Bean,通过源码解析:
通过上述实例的分析,可以总结springboot配置的大致逻辑如下:
三、@ComponentScan
这个是Spring提供的基本注解,可参考Spring相关注解文章。
总而言之:
根据不同的条件判断,决定这个配置类是否生效。一旦这个配置类生效,这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这个类里面的每个属性又是与配置文件绑定的。所有在配置文件中的配置属性都是在XXXProperties类中封装着,配置文件怎么配置属性可以参考对应的类属性。
精髓就是:
1、SpringBoot启动时会加载大量的自动配置列;
2、实际开发中需要实现的功能有没有SpringBoot默认写好的配置类;
3、如果有再看这个自动配置类中到底配置类哪些组件;(只要有需要的,即无需在进行配置了)
xxxAutoConfiguration:自动配置类,用于给容器中添加组件从而代替之前手动完成大量繁琐配置。
4、给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。这样开发者可以在配置文件中指定这些属性的值。
xxxProperties:封装了对应自动配置类的默认属性值,如果需要自定义属性值,只要根据该类寻找相关属性在配置文件设置即可。