SpringBoot自动配置原理
大约 2 分钟
SpringBoot自动配置原理
1、面试官:请说一下SpringBoot自动配置的原理
解答:
1. 在主启动类上添加了SpringBootApplication注解,这个注解组合了EnableAutoConfiguration注解
2. EnableAutoConfiguration注解又组合了Import注解,导入了AutoConfigurationImportSelector类
3. 实现selectImports方法,这个方法经过层层调用,最终会读取META-INF 目录下的 后缀名 为imorts的文件,当然了,boot2.7以前的版本,读取的是spring.factories文件
4. 读取到全类名了之后,会解析注册条件,也就是@Conditional及其衍生注解,把满足注册条件的Bean对象自动注入到IOC容器中
2、自动配置源码分析
遵守约定大于配置的原则,在Boot程序启动后,起步依赖中的一些bean对象会自动注入到IOC容器中
示例:程序引入spring-boot-starter-web 起步依赖,启动后,会自动往ioc容器中注入DispatcherServlet
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
启动类
@SpringBootApplication
public class BeanRegisterApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(BeanRegisterApplication.class, args);
System.out.println(context.getBean("dispatcherServlet"));
}
}
不引入spring-boot-starter-web
会报错如下:
Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'dispatcherServlet' available
引入会打印如下:
org.springframework.web.servlet.DispatcherServlet@6a4ccef7
@SpringBootApplication
分析
3、启动类注解源码中多个组合注解
......
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
......
}
第一个@SpringBootConfiguration
...... @Configuration public @interface SpringBootConfiguration { ...... }
存在@Configuration,说明启动类也是一个配置类
@EnableAutoConfiguration 【重要】
...... @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class}) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
组合注解中的 AutoConfigurationImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { ...... @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } ...... }
public interface DeferredImportSelector extends ImportSelector { ...... }
注意观察实现的是
DeferredImportSelector
,该接口继承的是ImportSelector。上面Bean注册 @import中使用过追溯源码发现会读取配置文件
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
。里面存放的是配置类的全类名。例如:
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
进入源码:@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) public class DispatcherServletAutoConfiguration { ...... @Configuration(proxyBeanMethods = false) @Conditional(DefaultDispatcherServletCondition.class) @ConditionalOnClass(ServletRegistration.class) @EnableConfigurationProperties(WebMvcProperties.class) protected static class DispatcherServletConfiguration { ...... @Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME) public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) { DispatcherServlet dispatcherServlet = new DispatcherServlet(); dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); configureThrowExceptionIfNoHandlerFound(webMvcProperties, dispatcherServlet); dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails()); return dispatcherServlet; } ...... } ...... }
最终读取配置类,解析注册条件,也就是@Conditional及其衍生注解,把满足注册条件的Bean对象自动注入到IOC容器中。
4、自动配置核心
核心是spring.factories 和 .imports 配置文件,也是配置类的全类名存放文件
5、版本支持
版本支持如下:
- SpringBoot版本 < SpringBoot2.7x,只支持spring.factories
- SpringBoot2.7x <= SpringBoot版本 < SpringBoot3.0 ,支持spring.factories 和 imports
- SpringBoot3.0之后, 只支持imports文件