美文网首页
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