关于java注解的基础知识,参见笔者的前一篇文章 Java Annotation 注解
1.序言
先回顾官方对于SpringBoot的一个概述:“Spring Boot 可以轻松创建可以“直接运行”的独立的、生产级的基于 Spring 的应用程序。”
Spring Boot 较于Spring最大的改进是简化了错综复杂的xml配置,通过Java的main方法启动程序。
这里就用到了Java的一个技术——注解,通过反射获取启动类的注解,进而根据注解的参数等启动整个框架。
2.@SpringBootApplication分析
@SpringBootApplication是Sprnig Boot项目的核心注解,目的是开启自动配置。
@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是个复合注解,除去4个jdk的元注解,还包含了三个注解:
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponentScan
2.1.@SpringBootConfiguration
作用:标注这个类是一个配置类。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
- 可以看到这个注解只是@Configuration注解的派生注解,跟@Configuration注解的功能一致。
- 只不过@SpringBootConfiguration是springboot的注解,而@Configuration是spring的注解。
- @Configuration 对我们来说并不陌生,它就是 JavaConfig 形式的 Spring IoC 容器的配置类使用的那个 @Configuration。
- 既然 SpringBoot 应用骨子里就是一个 Spring 应用,那么自然也需要加载某个 IoC 容器的配置。
- 而 SpringBoot 社区推荐使用基于 JavaConfig 的配置形式,所以,这里的启动类标注了 @SpringBootConfiguration之后,本身其实也是一个 IoC 容器的配置类!
2.2.@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
2.2.1.@AutoConfigurationPackage
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({AutoConfigurationPackages.Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
}
是将添加该注解的类所在的包 作为 自动配置package 进行管理。
从源码上看本质是@Import({AutoConfigurationPackages.Registrar.class}),@Import({AutoConfigurationPackages.Registrar.class})底层原理是通过反射将主配置类所在包及子包扫描到spring容器中。
2.2.2.@Import({AutoConfigurationImportSelector.class})
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;
}
借助AutoConfigurationImportSelector将所有符合自动配置条件的 bean 定义加载到 IoC 容器。
所以@EnableAutoConfiguration 其实就变成了:
- 从 classpath 中搜寻所有 META-INF/spring.factories 配置文件
- 并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration 对应的配置项
- 通过反射(Java Reflection)实例化为对应的标注了 @Configuration 的 JavaConfig 形式的 IoC 容器配置类,然后汇总为一个并加载到 IoC 容器。
2.3.@ComponentScan
Spring注解,自动扫描并加载符合条件的组件或 bean 定义,最终将这些 bean 定义加载到容器中。