Spring Boot 2 实战:@SpringBootApplication注解浅析
本文于 1500 天之前发表,文中内容可能已经过时。
1. 前言
Spring Boot 都会有一个名为 xxApplication
的启动类,里面有一个标准的 java 应用的入口 main 方法,用于启动 Spring Boot 应用项目。@SpringBootApplication
是Spring Boot的核心注解,作用在启动类上,在通常情况下Spring Boot在启动时会自动扫描 @SpringBootApplication
所在类的同级包及下级包里的所有 Bean 。为什么一个小小的注解就能发挥这么大的作用?今天我们来一探究竟。
2. @SpringBootApplication
我们就从@SpringBootApplication
注解源码开始一步步揭开谜底。看看这个注解都干了什么。
2.1 @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 {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
}
注解@SpringBootApplication
是个复合注解,集成了@ComponentScan
, @EnableAutoConfiguration
, @SpringBootConfiguration
三个注解。
2.2 @ComponentScan 注解
Spring里诸如@Service
,@Repository
,@Component
,@Controller
等用来向Spring IoC 容器注入bean。@ComponentScan
注解就是用来自动扫描被这些注解标识的类,使得这些类被发现并最终注入Spring IoC容器。你也可以通过设置@ComponentScan
中的basePackages
,includeFilters
,excludeFilters
属性来动态确定自动扫描包范围和过滤规则。默认情况下:它扫描所有类型,并且扫描范围是@ComponentScan注解所在配置类包及子包的类。
2.3 @EnableAutoConfiguration
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
这也是个复合注解,该注解可以帮助 Spring Boot 应用将所有符合条件的 @Configuration
配置都加载到当前 Spring Boot 创建并使用的 IoC 容器中。该注解的的核心要属于 @Import(AutoConfigurationImportSelector.class)
,AutoConfigurationImportSelector
是自动配置选择器。其中注解@Import
的作用是给容器中导入一个组件。
public class AutoConfigurationImportSelector
implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware,
BeanFactoryAware, EnvironmentAware, Ordered {
private static final AutoConfigurationEntry EMPTY_ENTRY = new AutoConfigurationEntry();
private static final String[] NO_IMPORTS = {};
private static final Log logger = LogFactory
.getLog(AutoConfigurationImportSelector.class);
private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
private ConfigurableListableBeanFactory beanFactory;
// 环境
private Environment environment;
// 类加载
private ClassLoader beanClassLoader;
// 资源加载
private ResourceLoader resourceLoader;
//----省略方法--------
}
该类实现了类加载器,资源加载器,BeanFactoryAware
和 EnvironmentAware
,借助 SpringFactoriesLoader
工具类通过类似java SPI
查找配置类的功能,实现了从 classpath
中搜寻所有 META-INF/spring.factories
配置文件,并将其中 org.springframework.boot.autoconfigure.EnableAutoConfiguration
对应的配置项通过反射实例化为标注了 @Configuration
的配置类,然后汇总加载到Spring IoC 容器。工作流程图为(来源于网络):
2.4 @SpringBootConfiguration 注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@SpringBootConfiguration
继承自@Configuration
,二者功能也一致,标注当前类是配置类,并会将当前类内声明的一个或多个以@Bean注解标记的方法的实例纳入到Spring IoC容器中,并且实例名就是方法名。 特别的是该注解标识这是一个 Spring Boot 项目。
3. 总结
我们简单总结一下Spring Boot的启动步骤。Spring Boot应用启动main方法后执行了一系列事件逻辑(加载环境等等)有兴趣可以去看源码,然后
@SpringBootApplication
起作用@SpringBootConfiguration
注入配置- 然后触发了
@EnableAutoConfiguration
的作用:
- 首先
@AutoConfigurationPackage
这个组合注解。加载AutoConfigurationPackages.Registrar
类,Registrar
类导入到容器中,而Registrar
类作用是扫描主配置类同级目录以及子包,并将相应的组件导入到Spring Boot创建管理的容器中。 - 然后将
AutoConfigurationImportSelector
导入到Spring IoC容器中,AutoConfigurationImportSelector
作用是通过selectImports
方法实现将配置类信息交给SpringFactoriesLoader
进行一系列的容器创建过程,具体实现可查看上面的源码。
@ComponentScan
扫描Spring Boot启动类同级以及子包扫描其中的Bean并注入Spring IoC容器。
评论系统未开启,无法评论!