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容器。
 
         
            
评论系统未开启,无法评论!