Springboot的自动装配原理浅析

2 篇文章 0 订阅
1 篇文章 0 订阅

最近在学习Springboot,不少文章和视频在完成了第一个快速入门的项目之后就直接进入了Springboot运行的原理部分,因此决定写一篇文章加深理解。

原理的理解主要使用了查看源码和画流程图的方式。

pom.xml

对于一个maven项目,我们一般首要分析其pom文件,查看相关依赖。

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

可以看到依赖方面都是很简单的内容,加入了测试启动器和web启动器以及springboot的build插件,但我们发现了一个不一般的地方,他们都没有版本号!这是为什么呢?
我们往上查看,可以发现这样的父依赖。

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

我们点进去查看,会发现。。。还有一层父依赖!

<parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-dependencies</artifactId>
 <version>2.3.4.RELEASE</version>
</parent>

继续点进去查看。

<properties>
    <activemq.version>5.15.13</activemq.version>
    <antlr2.version>2.7.7</antlr2.version>
    <appengine-sdk.version>1.9.82</appengine-sdk.version>
    <artemis.version>2.12.0</artemis.version>
    <aspectj.version>1.9.6</aspectj.version>
    <assertj.version>3.16.1</assertj.version>
    <atomikos.version>4.0.6</atomikos.version>
    <awaitility.version>4.0.3</awaitility.version>
    <bitronix.version>2.1.4</bitronix.version>
    <build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
    <byte-buddy.version>1.10.14</byte-buddy.version>
    <caffeine.version>2.8.5</caffeine.version>
    <cassandra-driver.version>4.6.1</cassandra-driver.version>
    ...........
    ```

这样的信息就是这些依赖尽头的主体了,这个文件有大量的配置信息,标注了每个可能用到的依赖的版本号,因此我们不用指定依赖的版本,springboot会根据你使用的版本自动给你安排合适的版本,再也不用担心依赖版本的冲突导致的崩溃啦!

pom.xml文件我们就说到这里,接下来才是重头戏了!

思维导图:
在这里插入图片描述

启动类的@SpringBootApplication注解

启动类包括两个重要的部分,一个是@SpringBootApplication注解,另一个是其中的run方法,我们先从这个注解开始说起。

首先,这个注解的作用,猜也猜得到,是标注这个应用是一个springboot应用,这样springboot就可以帮我们对其进行自动配置,我们想要了解,spring boot是如何通过注解来自动装配的,装配了什么。

老办法,查看源码,我点!

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

以上是@SpringBootApplication注解之下的几个注解,出去那些基础的之外,我们可以看见三个特别显眼的,@SpringBootConfiguration,@ComponentScan,@EnableAutoConfiguration,我们逐个查看他们的源码。

@SpringBootConfiguration

他的源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration

乏善可陈。。。根据其下的@Configuration可以猜到,它是起到一个标注作用的注解,标志当前应用为一个springboot应用。

我们回到上一层查看其他注解的源码。

@ComponentScan

这个更没啥好说的了,源码都没必要看了,他的作用是扫描指定包下的组件,将它们加载到Spring的IOC容器之中,很重要,但不是我们探究的重点。

我们查看最后一个注解的源码。

@EnableAutoConfiguration

看得出来,他的作用是启用自动配置,我们重点关注如何启用,怎么启用,启用了什么。
他的源码:

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

看起来重要的注解就这两个,第一个看翻译是自动配置包,我们点进去查看他的源码:

@Import({Registrar.class})

噢,这是一个注册器,根据相关源码猜测是将bean注册导入到容器之中(若有错误希望指正)。

我们回头,看看import导入的东西。

自动配置导入选择器,我们猜测它是导入了需要的配置文件,查看源码:
在这里插入图片描述
我这里截图还没有截全。。。我们发现其中有相当多的方法,我们的目的是查看如何加载组件的,因此寻找configuration相关的方法。

找到了!getCandidateConfigurations,获取候选配置,这个方法中又使用了SpringFactoriesLoader,我们继续深入。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
看到了看起来是文件的东西!我们使用全局搜索,发现它在springboot的jar包内,我们再点开来看看

在这里插入图片描述我们根据源头打开spring.factories , 看到了很多自动配置的文件;这就是自动配置根源所在!可以随便点开看看,都可以看到这些一个个的都是JavaConfig配置类,而且都注入了一些Bean。

至此,我们大概明白了Spring boot的自动装配原理了:

自动配置真正实现是从classpath中搜寻所有的META-INF/spring.factories配置文件 ,并将其中对应的 org.springframework.boot.autoconfigure. 包下的配置项,通过反射实例化为对应标注了 @Configuration的JavaConfig形式的IOC容器配置类 , 然后将这些都汇总成为一个实例并加载到IOC容器中。

所以其实刚刚那一大串套娃注解其实都是为了拿到spring.factories。。。我不太懂设计模式,不太懂这样做的意义是什么样的哈哈哈。

结论

  1. SpringBoot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值

  2. 将这些值作为自动配置类导入容器 , 自动配置类就生效 , 帮我们进行自动配置工作;

  3. 整个J2EE的整体解决方案和自动配置都在springboot-autoconfigure的jar包中;

  4. 它会给容器中导入非常多的自动配置类 (xxxAutoConfiguration), 就是给容器中导入这个场景需要的所有组件 , 并配置好这些组件 ;

  5. 有了自动配置类 , 免去了我们手动编写配置注入功能组件等的工作;

思维导图:
在这里插入图片描述

run方法

分析该方法主要分两部分,一部分是SpringApplication的实例化,二是run方法的执行;
SpringApplication

这个类主要做了以下四件事情:

1、推断应用的类型是普通的项目还是Web项目

2、查找并加载所有可用初始化器 , 设置到initializers属性中

3、找出所有的应用程序监听器,设置到listeners属性中

4、推断并设置main方法的定义类,找到运行的主类

源码分析无力了。。。给大家一张图吧,说的很清楚了,大家可以跟着这张图自己读读源码。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值