Java教程

SpringBoot自动装配原理分析

本文主要是介绍SpringBoot自动装配原理分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

在springBoot中,我们不需要做任何的配置,可以直接编写业务层面

的代码,原因就是springBoot帮我们配置好了所有的环境。

下面以一个简单的springboot项目进行分析

项目代码

springBoot主程序
```java
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

pom文件的部分代码

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

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

先来分析pom文件,每一个springBoot项目都会引入一个父项目,点击进入,发现里面还有一个父项目,spring-boot-dependencies,通过这个名字可知,这个项目跟依赖有关。

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

再点击进入,发现springBoot为我们声明了几乎所有开发中依赖的版本号,我们在引入依赖时,无需声明版本号,由springBoot为我们自动选择版本号。

<activemq.version>5.16.3</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.91</appengine-sdk.version>
<artemis.version>2.17.0</artemis.version>
<aspectj.version>1.9.7</aspectj.version>
<assertj.version>3.19.0</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<awaitility.version>4.0.3</awaitility.version>
<build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
<byte-buddy.version>1.10.22</byte-buddy.version>
<caffeine.version>2.9.2</caffeine.version>
......

接下来分析我们自己引入的依赖
官方文档:Starters 是一组方便的依赖描述符,您可以将它们包含在您的应用程序中。您可以获得所需的所有 Spring 和相关技术的一站式服务,而无需搜索示例代码和复制粘贴加载的依赖项描述符。

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

我们引入这个依赖,就相当于引入了所有跟web有关的依赖。
请添加图片描述
可以看出,引入了spring-webmvc,spring-web,tomcat,json,starter。

简单分析了一下pom文件,接下来的重点是,分析项目在运行的时候,如何将配置自动完成装配。

对springBoot的主程序进行分析,发现该类上标注的一个注解 @SpringBootApplication 从
名字可以看出,该注解指明这是一个SpringBoot的项目。

点击进入发现,该注解上还有以下两个注解,接下来逐个分析

@SpringBootConfiguration
@EnableAutoConfiguration

根据名字可知,@springBootConfiguration 是跟配置有关。
再点击进入发现 @springBootConfiguration 下 有一个@Configuration注解,表明我们的主程序HelloApplication 类一个配置类。

接下来看第二个注解 @EnableAutoConfiguration,根据名字就能知道,这个注解的作用是,完成自动配置的类。

点击进入,发现该注解上有两个注解,我们逐个分析

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

@AutoConfigurationPackage 根据名字可以知道,自动配置包,指定了默认的包规则,该注解的作用是,自动扫描主程序 HelloApplication 类 所在包的所有包。

我们点击进去,看看是怎么样完成这个功能的

@Import({Registrar.class})

此注解的作用是,将Registrat类加载进入容器中。
点击进入,看看该类的功能是什么。

发现一个方法,registerBeanDefinitions 注册定义的bean对象

public void registerBeanDefinitions(AnnotationMetadata metadata, 
									BeanDefinitionRegistry registry) {
	AutoConfigurationPackages.register(registry, (String[])(new 
	AutoConfigurationPackages.PackageImports(metadata)).
	getPackageNames().toArray(new String[0]));
}

AnnotationMetadata metadata 注解类的元数据,即为主程序 HelloApplication 类 的元数据
断点调试,发现(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames()
这个表达式的值就是 HelloApplication 类所在的包。
请添加图片描述
将主程序类HelloApplication所在的包下的所有组件加入容器。
现在就把 @AutoConfigurationPackage 这个注解的作用分析完成。
@EnableAutoConfiguration 还引入了一个类 @Import({AutoConfigurationImportSelector.class})

AutoConfigurationImportSelector 自动配置导入选择器。

点解进入该类,里面有一个方法selectImports ,选择导入

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

其中 这个getAutoConfigurationEntry方法,自动配置加载的方法。
在这个方法中,这一行语句,获得了要加载的所有配置的信息。

 List<String> configurations = this.getCandidateConfigurations
 (annotationMetadata, attributes);

请添加图片描述
进入getCandidateConfigurations 这个方法

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
    this.getSpringFactoriesLoaderFactoryClass(), this.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;
}

在 SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); 完成了加载。

点击进入 SpringFactoriesLoader 类中,发现

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

FACTORIES_RESOURCE_LOCATION 工厂的文件路径。也就是加载配置文件的路径。
springBoot 从 META-INF/spring.factories 这个文件中读取要加载的配置文件信息。

也就是下面这个包下面的这个文件。
请添加图片描述
打开文件发现 ,文件中有所有的要配置的信息。
请添加图片描述

当然,也不是所有的配置类都要加载。
每个自动配置类根据条件进行加载。
按照条件装配规则(@Conditional),最终会按需配置。。。。

 

这篇关于SpringBoot自动装配原理分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!