美文网首页
springboot注解@SpringBootApplicati

springboot注解@SpringBootApplicati

作者: loveFXX | 来源:发表于2020-01-14 22:05 被阅读0次

    springboot启动通过main方法,在main方法所在的类添加了SpringBootApplication注解

    示例代码

    启动类Application.class

    package com.netepg;
    
    @SpringBootApplication
    public class App{
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }
    

    SpringBootApplication注解元数据

    首先查看下在springboot中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 {
    
        /**
         * Exclude specific auto-configuration classes such that they will never be applied.
         * @return the classes to exclude
         */
        @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
        Class<?>[] exclude() default {};
    
        /**
         * Exclude specific auto-configuration class names such that they will never be
         * applied.
         * @return the class names to exclude
         * @since 1.3.0
         */
        @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
        String[] excludeName() default {};
    
        /**
         * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
         * for a type-safe alternative to String-based package names.
         * @return base packages to scan
         * @since 1.3.0
         */
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
        String[] scanBasePackages() default {};
    
        /**
         * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
         * scan for annotated components. The package of each class specified will be scanned.
         * <p>
         * Consider creating a special no-op marker class or interface in each package that
         * serves no purpose other than being referenced by this attribute.
         * @return base packages to scan
         * @since 1.3.0
         */
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
        Class<?>[] scanBasePackageClasses() default {};
    
    }
    

    注解主要包括SpringBootConfiguration、EnableAutoConfiguration、ComponentScan
    1、SpringBootConfiguration注解表明当前类是配置类


    image.png

    2、EnableAutoConfiguration注解表示开启自动配置
    3、ComponentScan表示,扫描过滤

    EnableAutoConfiguration注解

    @AutoConfigurationPackage
    @Import(EnableAutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {
    }
    

    这个注解元数据包括AutoConfigurationPackage和使用import导入了EnableAutoConfigurationImportSelector类
    1、AutoConfigurationPackage注解导入AutoConfigurationPackages.Registrar类


    image.png

    AutoConfigurationPackages.Registrar类实现了ImportBeanDefinitionRegistrar


    image.png
    AutoConfigurationPackages#register
    BEAN = "org.springframework.boot.autoconfigure.AutoConfigurationPackages"
    把AutoConfigurationPackages注册到bean工厂,并把当前包名设置为ConstructorArgumentValues参数
    image.png

    实现了ImportBeanDefinitionRegistrar的类,也会在生成bean的生命周期的import过程中,调用registerBeanDefinitions方法

    2、EnableAutoConfigurationImportSelector

    在spring容器实例化Bean的过程中,在解析配置类时,会对实现了DeferredImportSelector的导入类调用selectImports方法

    2.1、selectImports

    AutoConfigurationImportSelector#selectImports
    加载元数据


    image.png

    AutoConfigurationMetadataLoader#loadMetadata(java.lang.ClassLoader)


    image.png
    将会加载spring-autoconfigure-metadata.properties文件的数据。加载过程把配置文件中的值加载到Properties然后封装成AutoConfigurationMetadata对象返回
    image.png
    对于封装的属性配置元数据,加载META-INF/spring.factories数据

    经过去除重复值,去掉需要剔除的值,经过filter过滤处理

    2.2、getCandidateConfigurations

    AutoConfigurationImportSelector#getCandidateConfigurations
    查询带spring.factories文件的依赖包,获取所有值的键值对。通过EnableAutoConfiguration过滤出来需要自动加载的


    image.png

    AutoConfigurationImportSelector#getSpringFactoriesLoaderFactoryClass
    表示只加载EnableAutoConfiguration类型的类


    image.png
    2.3、removeDuplicates

    AutoConfigurationImportSelector#removeDuplicates
    移除重复的通过LinkedHashSet集合接收,然后转成ArrayList


    image.png
    2.4、sort

    对configurations集合排序 sort()

    2.5、getExclusions

    AutoConfigurationImportSelector#getExclusions
    剔除exclude excludeName


    image.png
    2.6、checkExcludedClasses

    checkExcludedClasses检查是否包含需要剔除的exclusions集合元素


    image.png
    2.7、filter

    AutoConfigurationImportSelector#filter


    image.png

    对configurations集合中的元素通过AutoConfigurationImportFilter过滤器实现类OnClassCondition进行过滤
    ①、match
    OnClassCondition#match


    image.png
    ②、getOutcomes
    OnClassCondition#getOutcomes
    image.png

    ③、resolveOutcomes
    分成两半调用resolveOutcomes方法
    OnClassCondition.StandardOutcomesResolver#resolveOutcomes


    image.png
    StandardOutcomesResolver#getOutcomes
    image.png
    PropertiesAutoConfigurationMetadata#get(String, String,String)
    image.png
    拼接className和ConditionalOnClass的字符串从properties查找
    StandardOutcomesResolver#getOutcomes方法返回没找到类的集合
    image.png
    OnClassCondition.StandardOutcomesResolver#getOutcome
    image.png
    image.png
    image.png
    image.png

    所以,ConditionOutcome集合存储的是加载不到的class
    根据ConditionOutcome[] outcomes集合获取是否match匹配值的集合


    image.png
    match是true,对不包含的进行跳过skip(true表示跳过,不包含)
    image.png
    image.png
    对包含的元素放入到result集合并返回
    image.png
    2.8、fireAutoConfigurationImportEvents

    AutoConfigurationImportSelector#fireAutoConfigurationImportEvents


    image.png

    AutoConfigurationImportSelector#invokeAwareMethods
    为监听器对象ConditionEvaluationReportAutoConfigurationImportListener设置beanFactory值


    image.png
    ConditionEvaluationReportAutoConfigurationImportListener#onAutoConfigurationImportEvent
    创建ConditionEvaluationReport用来记录评估和日志的条件评估细节类,从bean工厂获取

    condition.ConditionEvaluationReport#get
    beanName是autoConfigurationReport,ConditionEvaluationReport的条件评估细节类


    image.png
    image.png
    把evaluationCandidates和exclusions集合放入当前对象的属性中
    image.png
    最终是放到bean工厂的singletonOjects单例对象中
    image.png
    并selectImports方法返回configurations集合会放入到在processImports方法成配置类ConfigurationClass中

    spring.factories数据与spring-autoconfigure-metadata.properties数据对应关系

    基于2.1.x
    spring.factories

    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
    org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
    

    对于DispatcherServletAutoConfiguration、ServletWebServerFactoryAutoConfiguration、WebMvcAutoConfiguration类需要查找对于的spring-autoconfigure-metadata.properties的值
    spring-autoconfigure-metadata.properties

    org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration.ConditionalOnClass=org.springframework.web.servlet.DispatcherServlet
    org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration.ConditionalOnClass=javax.servlet.ServletRequest
    org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration.ConditionalOnClass=javax.servlet.Servlet,org.springframework.web.servlet.config.annotation.WebMvcConfigurer,org.springframework.web.servlet.DispatcherServlet
    

    如果能够加载org.springframework.web.servlet.DispatcherServlet类,则DispatcherServletAutoConfiguration会自动装配到bean工厂。
    能够加载javax.servlet.ServletRequest,则ServletWebServerFactoryAutoConfiguration自动装配到bean工厂

    ServletWebServerFactoryAutoConfiguration

    查找过程与类上条件相同@ConditionalOnClass(ServletRequest.class)


    image.png
    加载tomcat

    ServletWebServerFactoryAutoConfiguration类导入EmbeddedTomcat类,需要具有相关的类


    image.png
    说明:

    本章源码分析是基于1.5.x
    导入的类是EnableAutoConfigurationImportSelector
    EnableAutoConfigurationImportSelector实现了AutoConfigurationImportSelector
    2.1.x 直接导入的类是AutoConfigurationImportSelector
    selectImports方法的实现过程是一样的,只是抽出了一个方法


    image.png

    AutoConfigurationImportSelector#getAutoConfigurationEntry


    image.png

    总结:

    在自动装配中@ConditionalOnClass注解的使用
    在自动配置SpringBootApplication注解中使用导入外部类方式:
    1、实现了ImportBeanDefinitionRegistrar的类调用registerBeanDefinitions方法
    2、实现了ImportSelector的类调用selectImports方法
    @SpringBootApplication注解关键是如何读取数据并如何完成自动注入的
    首先从所有依赖包查询spring-autoconfigure-metadata.properties文件,读取里面的数据加载到自动配置类元数据类中。
    所有依赖包查询并获取spring.factories文件数据到集合中,然后经过去重,剔除处理。经过filter过滤步骤处理,会最终得到符合条件的类。
    在这个关键步骤filter中,主要过程是:
    1、spring.factories文件数据加载到集合的数据值拼接ConditionOnClass字段
    2、对拼接后的值,在spring-autoconfigure-metadata.properties加载的自动配置类元数据类中(以键值对形式存在)。查找对应的值
    3、对查找的值,通过类加载器查找是否能够加载到。返回一个match集合
    4、通过match集合确定skip集合是否可以跳过
    5、对于没有跳过的值,即可以通过类加载器加载的类放入到集合result中
    6、selectImports方法的返回值result可以在spring bean的生命周期过程中加载这些类生成相应的bean
    最终会加入到spring的bean工厂之中
    最终效果是完成了springboot的自动配置

    相关文章

      网友评论

          本文标题:springboot注解@SpringBootApplicati

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