我们知道SpringBoot的理念就是约定大于配置,这也使得我们在开发应用程序的过程更加便捷,以前的大量XML配置直接是噩梦呀,现在出现了SpringBoot明显降低了开发成本,而且大量的注解的使用帮我们省略掉了很多代码。本篇文章主要探究的是SpringBoot是如何实现自动配置并且如何加载配置Bean的,其实主要就是探究@EnableAutoConfiguration注解究竟发挥了怎样的作用。
@EnableAutoConfiguration
@SpringBootApplication其实是三个注解的组合体,这三个注解中@Configuration和@ComponentScan对我们来说并不陌生,今天我们主要探究的是@EnableAutoConfiguration
。
1 | (ElementType.TYPE) |
其中最关键的要属@Import(AutoConfigurationImportSelector.class),借助AutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器中。
借助于Spring框架原有的一个工具类:SpringFactoriesLoader的支持,@EnableAutoConfiguration可以智能的自动配置功效才得以大功告成!
在AutoConfigurationImportSelector类中可以看到通过SpringFactoriesLoader.loadFactoryNames()
把spring-boot-autoconfigure.jar/META-INF/spring.factories中每一个xxxAutoConfiguration文件都加载到容器中,spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解。
- @ConditionalOnClass : classpath中存在该类时起效
- @ConditionalOnMissingClass : classpath中不存在该类时起效
- @ConditionalOnBean : DI容器中存在该类型Bean时起效
- @ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
- @ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
- @ConditionalOnExpression : SpEL表达式结果为true时
- @ConditionalOnProperty : 参数设置或者值一致时起效
- @ConditionalOnResource : 指定的文件存在时起效
- @ConditionalOnJndi : 指定的JNDI存在时起效
- @ConditionalOnJava : 指定的Java版本存在时起效
- @ConditionalOnWebApplication : Web应用环境下起效
- @ConditionalOnNotWebApplication : 非Web应用环境下起效
SpringFactoriesLoader
SpringFactoriesLoader属于Spring框架私有的一种扩展方案(类似于Java的SPI方案java.util.ServiceLoader),其主要功能就是从指定的配置文件META-INF/spring-factories加载配置,spring-factories是一个典型的java properties文件,只不过Key和Value都是Java类型的完整类名,比如:
1 | xpu.MyService = xpu.MyServiceImpl |
对于@EnableAutoConfiguration来说,SpringFactoriesLoader的用途稍微不同一些,其本意是为了提供SPI扩展的场景,而在@EnableAutoConfiguration场景中,它更多提供了一种配置查找的功能支持,即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfig.EnableAutoConfiguration作为查找的Key,获得对应的一组@Configuration类。
SpringFactoriesLoader是一个抽象类,类中定义的静态属性定义了其加载资源的路径public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”,此外还有三个静态方法
- loadFactories:加载指定的factoryClass并进行实例化。
- loadFactoryNames:加载指定的factoryClass的名称集合。
- instantiateFactory:对指定的factoryClass进行实例化。
loadFactories还是调用了loadFactoryNames与instantiateFactory方法。loadFactories方法首先获取类加载器,然后调用loadFactoryNames方法获取所有的指定资源的名称集合、接着调用instantiateFactory方法实例化这些资源类并将其添加到result集合中。最后调用AnnotationAwareOrderComparator.sort方法进行集合的排序。
我们可以看一下SpringBoot的自动配置的Bean有哪些,见下图:
自动配置示例
下面结合一个例子来加深理解,例子展示的是当项目启动时如果某个类存在就自动配置这个Bean,并且这个属性可以在application.properties中配置。新建一个Maven项目,pom.xml文件如下:
pom.xml
1 |
|
Person.java
1 | package xpu.edu.tim; |
PersonProperties.java
1 | package xpu.edu.tim; |
PersonAutoConfiguration.java
1 | package xpu.edu.tim; |
spring.factories
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=xpu.edu.tim.PersonAutoConfiguration |
最后使用mvn package
将上面项目打包,使用mvn install:install-file
命令将打包文件上传到本地Maven仓库进行测试,下面再新建一个Maven项目用于测试。
1 |
|
IndexController.java
1 |
|
- 本文作者: Tim
- 本文链接: https://zouchanglin.cn/2020/04/06/3966649780.html
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!