美文网首页
SpringBoot—从 @SpringBootApplicat

SpringBoot—从 @SpringBootApplicat

作者: 牧呈 | 来源:发表于2020-07-23 09:52 被阅读0次

    0 @SpringBootApplication

    标识被注解的类是一个 @Configuration 类,在类中可以声明一个或多个 @bean 方法,并且它会触发 @EnableAutoConfiguration@ComponenetScan 的相应功能。@SpringBootApplication 注解是一个综合性注解,等同于声明 @Configuration@EnableAutoConfiguration@ComponentScan 这三个注解。

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
        // ...
    }
    

    @SpringBootApplication 的类声明中没有看到 @Configuration 注解,那是因为 @SpringBootConfiguration 其实就是一个 @Configuration`` 注解。至于@EnableAutoConfiguration``` 注解的魔法功能在下面会说到。

    这篇文章不谈论具体背后的工作原理,只是先认识跟 @SpringBootApplication 注解相关的其他几个注解,以及带来的作用。先把地基打好,才能建高楼大厦。

    1 @Import

    @Import 注解标识可以导入一个或多个 @Configuration 类。它提供的功能等同于以前 spring xml 配置中的 <import />标签,可以导入 @Configuration 类、ImportSelector 和 ImportBeanDefinitionRegistrar 的实现类,以及普通的组件类。如果 XML 或其他非 @Configuration 定义的 bean 资源需要被导入,可以使用 @ImportResource 注解。

    1.1 ImportSelector

    public interface ImportSelector {
        /**
         * 基于正在导入的 @Configuration 的 AnnotationMetadata 来选择应该被导入的类的名字
         */
        String[] selectImports(AnnotationMetadata importingClassMetadata);
    }
    

    ImportSelector 的子类可以实现任何下列 org.springframework.beans.factory.Aware Aware接口,它们各自的方法都会在 selectImports()方法之前被调用。

    • org.springframework.context.EnvironmentAware
    • org.springframework.beans.factory.BeanFactoryAware
    • org.springframework.beans.factory.BeanClassLoaderAware
    • org.springframework.context.ResourceLoaderAware

    1.2 ImportBeanDefinitionRegistrar

    public interface ImportBeanDefinitionRegistrar {
        /**
         * 基于正在导入的 @Configuration 的给定的注解元数据来注册 bean definition
         * bean definition 其实就是对 bean 的元数据信息封装。
         * 需要注意的是,BeanDefinitionRegistryPostProcessor 类型不会在这里注册,因为
         * 生命周期相关的约束。
         */
        void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
    
    }
    

    在处理 @Configuration 时,注册额外的 bean definition。

    2 @EnableAutoConfiguration

    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
        Class<?>[] exclude() default {};
    
        String[] excludeName() default {};
    
    }
    

    开启 Spring 应用上下文的自动配置功能,它试图猜测你可能需要配置的 bean

    2.1 @AutoConfigurationPackage

    @Import(AutoConfigurationPackages.Registrar.class)
    public @interface AutoConfigurationPackage {
    
    }
    

    表示包含该注解的类所在的包应该在 AutoConfigurationPackages 中注册。所以这个注解就能够解释为什么 spring boot 的启动类要放在 package 的最为层,以保证 spring 能够自动扫描到它们。

    它的实现原理是在注解上标注了 @Import,导入了一个AutoConfigurationPackages.Registrar

    2.1.1 AutoConfigurationPackages.Registrar

    用于保存导入的配置类所在的根包。它实现了 ImportBeanDefinitionRegistrar 接口。注意下,Registrar 类是 AutoConfigurationPackages 类的内部类,跟上面的注解 @AutoConfigurationPackage 名字就差了一个字母,别搞混了。

    static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        @Override
        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            register(registry, new PackageImport(metadata).getPackageName());
        }
    
        @Override
        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new PackageImport(metadata));
        }
    }
    

    2.2 AutoConfigurationImportSelector

    public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
            ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
        // ...
    }
    

    DeferredImportSelector 用于处理自动配置。如果需要自定义扩展 @EnableAutoConfiguration,那么也可以扩展此类。

    2.2.1 DeferredImportSelector

    public interface DeferredImportSelector extends ImportSelector {
        // ...
    }
    

    DeferredImportSelector 接口是 ImportSelector 接口的一种扩展,它是在处理完所有 @Configuration 类型的 bean 之后才会被执行,因此,它的执行时机是在 @Configuration 注解中的其他逻辑被处理完毕之后(包括对 @ImportResource@Bean 这些注解的处理)再执行,也就是说,DeferredImportSelector 的执行时机比 ImportSelector 更晚。

    DeferredImportSelector 接口在处理有条件的选择导入时非常有用。

    相关文章

      网友评论

          本文标题:SpringBoot—从 @SpringBootApplicat

          本文链接:https://www.haomeiwen.com/subject/srsclktx.html