本文基于SpringBoot 2.5.7版本进行讲解
我们知道所有的SpringBoot应用的启动类都会有一个@SpringBootApplication
注解。 这个注解就蕴含着SpringBoot自动配置的奥秘。
@SpringBootApplication是一个组合注解
@SpringBootApplication
注解的部分源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
复制代码
我们可以看到,@SpringBootApplication
是一个组合注解,它具有@SpringBootApplication
、@EnableAutoConfiguration
、@ComponentScan
三个注解的作用。
@SpringBootConfiguration
@SpringBootConfiguration
注解的源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
复制代码
可以看到@SpringBootConfiguration
注解本质上也只是一个@Configuration
注解,用于表示一个类是配置类。
类似于@Controller
、@Service
注解其实本质上也是一个@Component
注解,只是用于做语义化。@SpringBootConfiguration
注解也是用来表示一个配置类是SpringBoot的配置类。
@ComponentScan
这个注解是Spring的注解,用来开启注解扫描,会扫描出所有标注了@Component
注解的bean,并注入到容器中。这里不多做介绍。
@EnableAutoConfiguration
看名字就能知道,这个就是开启SpringBoot自动配置的核心注解。
@EnableAutoConfiguration
注解源码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
复制代码
了解@Import
注解的人就知道,这就是SpringBoot能够实现自动配置的原因了。
不了解@Import注解的,可以看Spring的@Import注解四种使用方式
AutoConfigurationImportSelector
实现了DeferredImportSelector
接口,而DeferredImportSelector
接口又继承了ImportSelector
接口。
因此,AutoConfigurationImportSelector
类是ImportSelector
的实现类。那么Spring就会将selectImports(AnnotationMetadata importingClassMetadata)
方法返回的类全限定名数组对应的beans配置到容器中。
这样就SpringBoot就完成了自动配置的功能。
注:其实在SpringBoot中并不是通过
AutoConfigurationImportSelector
的selectImports()
方法来获取需要配置的bean。后面我会写一篇文章讲解AutoConfigurationImportSelector
在SpringBoot中如何加载Bean。