springboot自动装配原理解析(源码级别详细解析)

首先我们先看下核心文件
1.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.7.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.qiu</groupId>
    <artifactId>springboot-01-helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-01-helloworld</name>
    <description>qiu first springboot project</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <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>

</project>

先挑出第一个来细讲:

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

点进去看源码:

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

结果又来了一个parent,这个时候我们再点进去看
在这里插入图片描述
终于没有了
再往下滑动会发现:
这里管理存放着大量的jar包.
所以说pom.xml里

  • spring-boot-dependencies:核心依赖在父工程中
    所以说这就是为什么不用写版本号的原因,因为上面的父工程已经管理了,有这些管理仓库了.
    2.启动器
 <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>` 

启动器:说白了就是springboot的启动场景

  • 比如说spring-boot-starter-web,他就会帮我们自动导入web环境下所有的依赖
  • springboot会将所有的功能场景会变成一个个启动器
  • 我们要使用什么功能就只需要找到对应的启动器就好了 starter
  • 在这里插入图片描述在这里插入图片描述然后就是主程序了:
    3.主程序
package com.qiu;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Springboot01HelloworldApplication {

    public static void main(String[] args) {
        SpringApplication.run(Springboot01HelloworldApplication.class, args);
    }

}

先看主程序的注解:
@SpringBootApplication:标注这个类是一个springboot的应用

SpringApplication.run:将springboot的应用启动

  • 注解:我们查看源码
    在这里插入图片描述

@SpringBootConfiguration:springboot的配置
在这里插入图片描述@Configuration:spring配置类:说明启动类也是一个配置类
然后在点进去:
在这里插入图片描述@Component:说明这也是一个spring的组件

@EnableAutoConfiguration:自动配置
点击源码进去:
在这里插入图片描述@AutoConfigurationPackage:自动配置包:自动配置包注册
在这里插入图片描述在这里插入图片描述
@Import(AutoConfigurationImportSelector.class):自动导入选择
再点进去:

这个类中的一段代码如下:获取所有的配置

List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)

getCandidateConfigurations:或者候选的配置

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
				getBeanClassLoader());
		Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
				+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

在这里插入图片描述为的就是将启动类中所有资源被导入
META-INF/spring.factories:自动配置的核心文件
在这里插入图片描述在这里插入图片描述 Properties properties = PropertiesLoaderUtils.loadProperties(resource);
所有的资源加载到配置类中
在这里插入图片描述
结论:springboot的所有自动配置都是在启动的时候扫描并加载 spring.factories但是不一定生效,要判断条件是否成立,只要导入了对应的start,就有了对应的启动器,有了启动器,我们的自动装配,就会生效,然后就配置成功了
步骤:

  1. springboot在启动的时候,从类路径下/META-INF/spring.factories获取指定的值
  2. 将这些自动配置的类导入容器,自动配置类就会生效,帮我们自动配置
  3. 以前我们需要自动配置的东西,现在springboot帮我们做了
  4. 整个javaEE,解决方案和自动配置的东西都在 spring-boot-autoconfigure-2.2.7.RELEASE.jar里面
  5. 它会把所有需要导入的组件,以类名的方式返回,这些组件就会被添加到容器
    在这里插入图片描述

6.容器中也会存在非常多的XXXAutoConfiguration的文件,就是这些类给容器中导入这些场景需要的所有的组件,并自动配置@Configuration,javaConfig
7. 有了自动配置类,免去了我们手动编写配置文件的工作

问题:
我们都知道:spring.factories这个文件中有所有的配置类,为什么这么多配置类中有的文件没有生效,而需要导入对应的start才能起作用?
核心注解@ConditionOn XXX :如果这里面的条件都满足才会生效!
比如说会判断jar包存不存在,如果不存在则所相对应的类就不会生效,所以说就算遍历了全部的配置类,但也不是说一定都有用.

上面一大串都是在将关于注解里面的,但是在主程序中不止是注解,他还有一个SpringApplication类,还有一个run方法
首先:springAppllication:
这个类主要做了以下四件事情:

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

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

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

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

查看构造器:

public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) {
    // ......
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.setInitializers(this.getSpringFactoriesInstances();
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = this.deduceMainApplicationClass();
}

在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值