- Spring Boot开发实战
- 陈光剑
- 812字
- 2023-07-26 14:26:43
3.3 Spring Boot自动配置过程
Spring Boot内置自动配置原理是怎样的呢?这一切都在@EnableAutoConfiguration这个注解里:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration
其中的核心注解是@Import(EnableAutoConfigurationImportSelector.class),借助Enable-AutoConfigurationImportSelector、@EnableAutoConfiguration、Spring Boot应用将所有符合条件的@Configuration配置类都加载到当前Spring容器中——就像一只“八爪鱼”一样。具体的实现是使用了Spring框架中原有的一个工具类SpringFactoriesLoader。这样,@EnableAutoConfiguration就可以智能实现Bean的自动配置。
3.3.1 @EnableAutoConfiguration注解
Spring Boot中通过@EnableAutoConfiguration启用Spring应用程序上下文的自动配置,这个注解会导入一个EnableAutoConfigurationImportSelector的类,而AutoConfigurationImportSelector这个类会去读取一个spring.factories下key为EnableAutoConfiguration对应的类全限定名的值。其中的关键代码如下:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
这个spring.factories里面配置的那些类,主要作用是告诉Spring Boot这个stareter所需要加载的那些*AutoConfiguration类,也就是你真正的要自动注册的那些Bean或功能。然后,再实现一个spring.factories指定的类,标上@Configuration注解,一个starter就定义完了。通过org.springframework.boot.autoconfigure.AutoConfigurationImportSelector里面的getCandidateConfigurations方法,获取到候选类的名字列表List<String>。
其中,loadFactoryNames的第1个参数是getSpringFactoriesLoaderFactoryClass()方法直接返回的是EnableAutoConfiguration.class,代码如下:
protected Class<? > getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
所以,getCandidateConfigurations方法里面的这段代码:
List<String> configurations = SpringFactoriesLoader.loadFactoryNames( getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
会过滤出key为
org.springframework.boot.autoconfigure.EnableAutoConfiguration
的全限定名对应的值。其中,SpringFactoriesLoader主要用来查询META-INF/spring. factories的properties配置中指定class对应的所有实现类。下节介绍这个文件。
提示
全限定名都使用如下命名方法:
包名.外部类名
包名.外部类名$内部类名
例如:
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfi guration
3.3.2 spring.factories文件
Spring Boot中的META-INF/spring.factories(spring-boot/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories)配置文件的完整内容可参考Spring Boot源代码工程,其中关于EnableAutoConfiguration的配置是:
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAut oConfiguration, \ …… org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
当然了,这些AutoConfiguration不是所有都会加载的,会根据AutoConfiguration上的@ConditionalOnClass等条件,再进一步判断是否加载。
3.3.3 获取候选配置类
在上面的getCandidateConfigurations方法中,我们可以看到读取spring.factories文件由SpringFactoriesLoader来完成的。SpringFactoriesLoader的实现类似于SPI(Service Provider Interface,在java.util.ServiceLoader的文档里有比较详细的介绍。Java SPI提供一种服务发现机制,为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要。
SpringFactoriesLoader会加载classpath下所有JAR文件里面的META-INF/spring.factories文件。
其中加载spring.factories文件的代码在loadFactoryNames()方法里。Spring Boot自动配置的过程可以用一张图说明,如图3-3所示。
图3-3 Spring Boot Autoconfigure工作原理图