以基于maven的和缺省配置的Spring Boot + Spring Web MVC应用项目为例观察Spring Boot自动配置机制如何工作 :
1.pom.xml 引入依赖spring-boot-autoconfigure
// 以下pom.xml 对 spring-boot-autoconfigure 的依赖引入是隐含的,不是直接引入。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>andy.tut.springboot</groupId>
<artifactId>zero</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<dependencies>
// 缺省配置 Springboot Web 项目的直接依赖,
// 隐含的依赖 :
// org.springframework.boot:spring-boot-starter
// |--org.springframework.boot:spring-boot
// |--org.springframework.boot:spring-boot-autoconfigure
// |--org.springframework.boot:spring-boot-starter-logging
// |--org.springframework:spring-core
// |--org.yaml:snakeyaml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
通过引入依赖spring-boot-autoconfigure,相应的jar包会出现在Springboot应用运行时的classpath中。
2.Spring Boot应用入口类使用注解@SpringBootApplication
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
注解@SpringBootApplication隐含了spring-boot-autoconfigure的注解@EnableAutoConfiguration,
而注解@EnableAutoConfiguration上又有注解@Import(EnableAutoConfigurationImportSelector.class)。
这个@Import(EnableAutoConfigurationImportSelector.class)在Springboot应用启动时做的就是spring-boot-autoconfigure被设计用来完成的工作:auto configure , 自动配置。
// 注解链
@SpringBootApplication
=>@EnableAutoConfiguration
=> @Import(EnableAutoConfigurationImportSelector.class)
3.应用启动时ConfigurationClassPostProcessor的注册
Springboot 应用在启动时,会创建一个ApplicationContext上下文实例。如果是Web应用,该上下文实例会使用类 AnnotationConfigEmbeddedWebApplicationContext来创建;否则使用类AnnotationConfigApplicationContext来创建。
不管是以上两种情况中的哪一种,相应的上下文类实例在创建时都会创建一个AnnotatedBeanDefinitionReader实例用于读取注解方式的Bean定义,而在创建这个AnnotatedBeanDefinitionReader实例的过程中,它注册了一个 ConfigurationClassPostProcessor Bean定义到容器,这是一个BeanFactoryPostProcessor,更明确地讲,它是一个BeanDefinitionRegistryPostProcessor。
ConfigurationClassPostProcessor被设计用来发现所有的配置类和相关的Bean定义并注册到容器,它在所有BeanFactoryPostProcessor中具备最高执行优先级,因为其他BeanFactoryPostProcessor需要基于注册了Bean定义工作。
spring-boot-autoconfigure自动配置的"自动"属性,主要就是通过这个机制来体现的 :
-
Spring容器启动时会在任何bean被使用前对该bean应用所有注册到容器中的BeanDefinitionRegistryPostProcessor; -
ConfigurationClassPostProcessor正是这样一个BeanDefinitionRegistryPostProcessor,并且在容器构造最早期就被注册了进来; -
ConfigurationClassPostProcessor的工作就是发现classpath中所有的符合条件的配置类并注册相应的bean定义,也就是执行了所谓的自动配置任务; -
spring-boot-autoconfigure包在开发阶段已经被引入了应用的classpath中。
4.应用启动时spring-boot-autoconfigure自动配置任务的执行
spring-boot-autoconfigure被设计用来在springboot启动过程中完成自动配置,这个自动配置通过上述设置后,会在springboot启动过程中,具体的来讲,是在以下位置被完成 :
SpringApplication.run()
=> refreshContext()
=> AbstractApplicationContext.refresh()
=> invokeBeanFactoryPostProcessors()
=> ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry()
=> processConfigBeanDefinitions()
=> ConfigurationClassParser.parse()
=> processDeferredImportSelectors()
=> AutoConfigurationImportSelector.selectImports()
下面是spring-boot-autoconfigure jar包内文件的结构。
spring-boot-autoconfigure jar包的文件结构
├─META-INF
│ spring-autoconfigure-metadata.properties
│ spring.factories
│
└─org
└─springframework
└─boot
└─autoconfigure
有几个很重要的信息 :
-
META-INF/spring-autoconfigure-metadata.properties包含了自动配置元数据。 -
META-INF/spring.factories使用属性org.springframework.boot.autoconfigure.EnableAutoConfiguration定义了哪些类是自动配置类,使用属性org.springframework.boot.autoconfigure.AutoConfigurationImportFilter定义了哪些自动配置导入过滤器会被应用,缺省情况下,只有一个过滤器会被应用,那就是OnClassCondition。 -
在包
org.springframework.boot.autoconfigure存在很多@Configuration注解的候选配置类。
AutoConfigurationImportSelector.selectImports()在执行时 :
-
从
spring-autoconfigure-metadata.properties属性文件中提取自动配置元数据AutoConfigurationMetadata; -
获取
spring.factories属性文件中属性org.springframework.boot.autoconfigure.EnableAutoConfiguration定义的所有配置类作为候选配置类; -
然后,获取
spring.factories属性文件中属性org.springframework.boot.autoconfigure.AutoConfigurationImportFilter定义的过滤器,缺省是一个 :org.springframework.boot.autoconfigure.condition.OnClassCondition -
对所有的候选配置类在自动配置元数据上应用所发现的过滤器,其实缺省情况下就一个,就是
OnClassCondition,也就是利用每个候选配置类上的注解@ConditionalOnClass, 来看这个候选配置类是否需要被应用。 -
selectImports()会返回所有需要被应用的配置类(注解@ConditionalOnClass条件被满足),ConfigurationClassPostProcessor.postProcessBeanFactory()会将识别这些配置类中定义的bean并将它们注册到容器。
具体的处理逻辑可以参考 :
2274

被折叠的 条评论
为什么被折叠?



