列位看官大家好,但凡是使用过springboot的小伙伴,一定有一种好奇,那些个烦人的配置文件到底去哪里了,怎么说消失就消失了呢,说走就走还让我有点不踏实呢,那么这些烦人的家伙真的了无牵挂的走了吗,今天让我们来一探究竟!
要搞明白这个问题我们从一个注解开始...
/**
*
* @SpringBootApplication 来标注一个主程序类,说明这是一个Spring Boot应用
*/
@SpringBootApplication
public class BaseApplication {
public static void main(String[] args) {
SpringApplication.run(BaseApplication.class,args);
}
}
@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 {
该注解标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot 就应该运行这个类的main方法来启动SpringBoot应用
跟我们本次探讨的话题有关的主要是@SpringBootConfiguration和@EnableAutoConfiguration这个两个注解
@SpringBootConfiguration
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
该类上加了一个@Configuration,在spring中,类上加该注解表示该类为配置类,所以,被@SpringBootConfiguration标注的则为Spring Boot的配置类,配置类就相当于配置文件
再说@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 {};
}
这里我们主要关注@AutoConfigurationPackage(自动配置包)和@Import(EnableAutoConfigurationImportSelector.class) (指定导入组件)
@AutoConfigurationPackage(自动配置包)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}
@Import(AutoConfigurationPackages.Registrar.class)
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
registerBeanDefinitions()调用register()将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器
@Import(EnableAutoConfigurationImportSelector.class) (指定导入组件)
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
该类中的selectImports()调用getCandidateConfigurations()调用SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class,classLoader);
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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容器中,以便使用
比如我们使用消息队列,该方法就给我们导入RabbitAutoConfiguration
总结
Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效,帮我们进行自动配置工作
类有点多,有点绕,大家主要吧这张图记住就可以啦