Spring boot源码分析一

2021/4/16 22:27:52

本文主要是介绍Spring boot源码分析一,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、springBoot的start机制

        Spring boot中的starter概念是非常重要的机制,能够抛弃以前繁杂的配置,统一集成进starter,应用者只需要引入starter jar包,spring boot就能自动扫描到要加载的信息。Spring Boot 通过starter对项目的依赖进行统一管理. starter利用了maven的传递依赖解析机制,把常用库聚合在一起, 组成了针对特定功能而定制的依赖starter。

 

  starter机制是将经过测试不会起冲突的相关maven依赖聚合在一起形成新的pom文件。直接引入相关start就相当于引入了相关依赖。

比如我们引入spring-boot-starter-jdbc 依赖 该包下并没有任何其他的java文件只有pom 只包含了对应的jdbc相关的maven依赖。

 

   

 

springBoot自动配置原理

  1、自动装配入口 

       @SpringBootApplication是一个组合注解其中的@EnableAutoConfiguration是实现自动装配的入口,该注解引入了一个AutoConfigurationImportSelector(在springBoot 1.3 之后开始使用EnableAutoConfigurationImportSelector实现自动装配,但是在springBoot1.5以后开始使用AutoConfigurationImportSelector来实现自动装配)

一、springBoot的start机制

        Spring boot中的starter概念是非常重要的机制,能够抛弃以前繁杂的配置,统一集成进starter,应用者只需要引入starter jar包,spring boot就能自动扫描到要加载的信息。Spring Boot 通过starter对项目的依赖进行统一管理. starter利用了maven的传递依赖解析机制,把常用库聚合在一起, 组成了针对特定功能而定制的依赖starter。

 

  starter机制是将经过测试不会起冲突的相关maven依赖聚合在一起形成新的pom文件。直接引入相关start就相当于引入了相关依赖。

比如我们引入spring-boot-starter-jdbc 依赖 该包下并没有任何其他的java文件只有pom 只包含了对应的jdbc相关的maven依赖。

 

   

 

springBoot自动配置原理

  1、自动装配入口 

       @SpringBootApplication是一个组合注解其中的@EnableAutoConfiguration是实现自动装配的入口,该注解引入了一个AutoConfigurationImportSelector(在springBoot 1.3 之后开始使用EnableAutoConfigurationImportSelector实现自动装配,但是在springBoot1.5以后开始使用AutoConfigurationImportSelector来实现自动装配)

// 注解链

@SpringBootApplication

    => @EnableAutoConfiguration

        => @Import(AutoConfigurationImportSelector.class)

2、AutoConfigurationImportSelector自动装配类

       该类通过@Import注解在spring项目启动的时候引入进行实例化该配置类,实例化该类后会调用其内部类的AutoConfigurationGroup的process和selectImports进行自动装配,调用链如下:

ConfigurationClassParser#parse(jBeanDefinitionHolder)

   =>DeferredImportSelectorHandler#process()

     =>DeferredImportSelectorGroupingHandler#processGroupImports()

       =>ConfigurationClassParser.DeferredImportSelectorGrouping#getImports()

          =>AutoConfigurationGroup的process() 和selectImports()

 

ConfigurationClassParser入口以及有关@Import导入流程我们择机再写。

 

2.1、process()方法

/**
     * @param annotationMetadata @SpringBootApplication注解元数据
     * @param deferredImportSelector 持有的一个自动装配对象 使用该类实现自动装配
     */
    public void process(AnnotationMetadata annotationMetadata,
                        DeferredImportSelector deferredImportSelector) {
        //断言语句
        Assert.state(
                deferredImportSelector instanceof AutoConfigurationImportSelector,
                () -> String.format("Only %s implementations are supported, got %s",
                        AutoConfigurationImportSelector.class.getSimpleName(),
                        deferredImportSelector.getClass().getName()));
        //获取springBoot应用红的所有的使用@Configuration修饰的配置类以及不需要排除的配置类
        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
                .getAutoConfigurationEntry(getAutoConfigurationMetadata(),
                        annotationMetadata);
        //将获取到的全部配置类添加到两个集合中便于后续的使用
        // autoConfigurationEntries(list自动配置类) 
        // entries(map以配置类名和@SpringBootApplication注解元数据 key-value的形式存放)
        this.autoConfigurationEntries.add(autoConfigurationEntry);
        for (String importClassName : autoConfigurationEntry.getConfigurations()) {
            this.entries.putIfAbsent(importClassName, annotationMetadata);
        }
    }

上面的方法很好理解就是从项目中获取所有的配置类,从而在后面启动过程中将配置中的相关bean对象进行实例化。关键是配置类在哪里呢我们如何获取所有的配置类呢,这就要看getAutoConfigurationEntry()方法了。

SpringFactoriesLoader会加载classpath下所有JAR文件里面META-INF/spring.factories文件,这样在通过实例化配置类中的相关bean从而完成自动装配。

 

2、AutoConfigurationImportSelector自动装配类

       该类通过@Import注解在spring项目启动的时候引入进行实例化该配置类,实例化该类后会调用其内部类的AutoConfigurationGroup的process和selectImports进行自动装配,调用链如下:

ConfigurationClassParser#parse(jBeanDefinitionHolder)

=>DeferredImportSelectorHandler#process()

=>DeferredImportSelectorGroupingHandler#processGroupImports()

  =>ConfigurationClassParser.DeferredImportSelectorGrouping#getImports()

    =>AutoConfigurationGroup的process() 和selectImports()

 ConfigurationClassParser入口以及有关@Import导入流程我们择机再写。

 

2.1、process()方法

/**

     * @param annotationMetadata @SpringBootApplication注解元数据

     * @param deferredImportSelector 持有的一个自动装配对象 使用该类实现自动装配

     */

    public void process(AnnotationMetadata annotationMetadata,

                        DeferredImportSelector deferredImportSelector) {

        //断言语句

        Assert.state(

                deferredImportSelector instanceof AutoConfigurationImportSelector,

                () -> String.format("Only %s implementations are supported, got %s",

                        AutoConfigurationImportSelector.class.getSimpleName(),

                        deferredImportSelector.getClass().getName()));

        //获取springBoot应用红的所有的使用@Configuration修饰的配置类以及不需要排除的配置类

        AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)

                .getAutoConfigurationEntry(getAutoConfigurationMetadata(),

                        annotationMetadata);

        //将获取到的全部配置类添加到两个集合中便于后续的使用

        // autoConfigurationEntries(list自动配置类)

        // entries(map以配置类名和@SpringBootApplication注解元数据 key-value的形式存放)

        this.autoConfigurationEntries.add(autoConfigurationEntry);

        for (String importClassName : autoConfigurationEntry.getConfigurations()) {

            this.entries.putIfAbsent(importClassName, annotationMetadata);

        }

    }

上面的方法很好理解就是从项目中获取所有的配置类,从而在后面启动过程中将配置中的相关bean对象进行实例化。关键是配置类在哪里呢我们如何获取所有的配置类呢,这就要看getAutoConfigurationEntry()方法了。

 /**

     *

     * @param autoConfigurationMetadata 自动化配置类注解元数据信息 用于过滤不符合条件的配置类

     * @param annotationMetadata #@SpringBootApplication注解 元数据信息

     * @return

     */

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(

            AutoConfigurationMetadata autoConfigurationMetadata,

            AnnotationMetadata annotationMetadata) {

        if (!isEnabled(annotationMetadata)) {

            return EMPTY_ENTRY;

        }

        //获取@SpringBootApplication 的EnableAutoConfiguration自动装配相关的属性

        // exclude和excludeName(显示设置的不需要进行自动化配置的配置类)

        AnnotationAttributes attributes = getAttributes(annotationMetadata);

        //SpringFactoriesLoader.loadFactoryNames获取项目中所有jar中META-INF/spring.factories下的所有配置类

        List<String> configurations = getCandidateConfigurations(annotationMetadata,

                attributes);

        //去重

        configurations = removeDuplicates(configurations);

        //获取不需要自动装配的配置类 依据注解中的exclude和excludeName

        Set<String> exclusions = getExclusions(annotationMetadata, attributes);

        checkExcludedClasses(configurations, exclusions);

        configurations.removeAll(exclusions);

        //过滤掉不符合条件的自动化配置类

        configurations = filter(configurations, autoConfigurationMetadata);

        //向所有的AutoConfigurationImportListener发送AutoConfigurationImportListener事件通知

        fireAutoConfigurationImportEvents(configurations, exclusions);

        return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);

    }

SpringFactoriesLoader会加载classpath下所有JAR文件里面META-INF/spring.factories文件,这样在通过实例化配置类中的相关bean从而完成自动装配。

 



这篇关于Spring boot源码分析一的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程