SpringBoot启动过程 - @SpringBootApplication
SpringBoot 的启动过程如下:
1 2 3 4 5 6 7 @SpringBootApplication public class SpringbootlLearningApplication { public static void main(String[] args) { SpringApplication.run(SpringbootlLearningApplication.class, args); } }
SpringBoot 简化了大量的配置的信息,几行代码就将 Spring Boot 服务启动,具体观察一下,有两部分指的注意:
@SpringBootApplication 注解去指定启动类
SpringApplication.run(SpringbootLearingApplication.class, args) 启动 Spring 容器
@SpringBootApplication 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @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 是一个组合注解,它包含了以下三个重要的注解:
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
@SpringBootConfiguration 1 2 3 4 5 6 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { }
可以看出,@SpringBootConfiguration 实际上就是一个配置注解,与 @Configuration 不同的是,一个应用程序中只能使用一个 @SpringBootConfiguration,而在我们启动 SpringBootApplication 的时候就已经开启配置,而 @Configuration 可以根据需要进行 JavaConfig 的方式进行多个实例配置
@EnableAutoConfiguration 1 2 3 4 5 6 7 8 9 10 11 12 13 @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 {}; }
@EnableAutoConfiguration这个复合annotation 的主要作用是开启容器的自动配置功能,而具体由 @AutoConfigurationPackage 和 @Import({AutoConfigurationImportSelector.class}) 实现。
@AutoConfigurationPackage 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import({Registrar.class}) public @interface AutoConfigurationPackage { } static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { Registrar() { } public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()); // 注册组件bean信息 } public Set<Object> determineImports(AnnotationMetadata metadata) { return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata)); } }
AutoConfigurationPackages.Register 会向 Spring 容器中注册所有包下的的组件Bean 信息,例如:我们自定义一个 Bean
1 2 3 4 5 6 7 @Component public class HelloService { void sayHello(){ System.out.println("hello"); } }
Debug 的时候就会发现,我们自定义的 component HelloService 被加入到 BeanDefinitionMap中,准备进行注入容器中
@Import({AutoConfigurationImportSelector.class}) @Import({AutoConfigurationImportSelector.class}) 这个注解主要是借助 @Import 的帮助,将符合自动配置 auto configure 的bean加载到容器中。
1 2 3 4 5 6 7 8 AutoConfigurationImportSelector.class protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { // 这里获取了 auto configurate的所有类文件名 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; }
加载这些 auto configurate 的类文件主要是借助于 SpringFactoriesLoader 进行实现的,SpringFactoriesLoader 会根据 配置的key即(@EnableAutoConfiguration 的路径,为 org.springframework.boot.autoconfigure )下,找到指定的配置文件如 META-INF/spring.factories 加载对应的 auto configure class,并加入到容器中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\ org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\ org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\ ...
@ComponentScan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { @AliasFor("basePackages") String[] value() default {}; @AliasFor("value") String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; String resourcePattern() default "**/*.class"; boolean useDefaultFilters() default true; ComponentScan.Filter[] includeFilters() default {}; ComponentScan.Filter[] excludeFilters() default {}; boolean lazyInit() default false; @Retention(RetentionPolicy.RUNTIME) @Target({}) public @interface Filter { FilterType type() default FilterType.ANNOTATION; @AliasFor("classes") Class<?>[] value() default {}; @AliasFor("value") Class<?>[] classes() default {}; String[] pattern() default {}; } }
@ComponentScan 这个注解的主要功能就是自动扫描并加载符合条件的组件,如 @Component 和 @Repository,并将组件加入到容器中,根据属性配置 basePackage可以指定扫描的范围