【SpringBoot 系列(一)】:浅析SpringBoot 的自动装配机制

924 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

前言

我们想在要创建一个 Spring 项目有多简单?

  1. 使用 Spring Initializer 创建一个 SpringBoot 项目
  2. 得到一个 Application.java
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

运行 Application.java,项目就可以启动了,如果我们对默认的配置不满意,或者需要补充或覆盖默认的配置,我们直接在 application.properties 配置文件中就可以搞定。

为什么 SpringBoot 可以用起来这么酸爽呢?这一切都得益于 SpringBoot 的自动装配,本文就来探究一下 SpringBoot 的自动装配原理。

什么是自动装配?

事实上,自动装配并不是 SpringBoot 实现的,在 Spring 框架中早就有了这个功能,但 SpringBoot 在这基础上,通过 SPI 的方式,做了进一步的优化,让自动装配更好用。

Spring Boot 遵循约定大于配置的原则,定义了一套接口规范,这套规范规定:Spring Boot 在启动时会扫描外部引用 jar 包中的 META-INF/spring.factories 文件,将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 Spring Boot 定义的标准,就能将自己的功能自动装配到 Spring Boot。

在 SpringBoot 中,如果我们要使用某些第三方依赖,我们直接在项目中引入 starter 即可,比如下面的例子。

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

如果你的 Redis 部署在本地,你甚至不需要任何配置就能直接使用代码开始操控 Redis,而不需要进行任何配置。

自动装配流程

还是以 spring-boot-starter-data-redis 为例,我们来看一下 Spring Boot 是如何进行自动装配的。

1)引入依赖

首先我们会在一个项目中,引入某个版本的 spring-boot-starter-data-redis 的依赖,前提是它与我们的 Spring Boot 版本兼容,对于胡乱的版本引入,项目出现依赖冲突的概率接近必然。

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
	<version>2.6.5-SNAPSHOT</version>
</dependency>

2)获取 Redis 相关配置类的全限定名

spring-boot-actoconfigure.jar/META-INF/spring.factories 中,有很多很多功能配置类的全限定名,一般一个功能配置类围绕该功能,负责管理创建多个相关的功能类,比如 org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration 负责管理和创建 JedisConnectionFactor、RedisTemplate、StringRedisTemplate 这几个功能类的创建。

image.png

这里的重点是 @ConditionalOnClass 注解,这个声明意味着在 classpath 路径下如果存在 RedisOperations.class,那么 RedisAutoConfiguration 就是生效的。

我们在第一步的时候引入了 Redis 的 starter 依赖,这样 Spring Boot 的自动装配机制就能在 classpath 下找到 RedisOperations.class

4)注入默认的属性配置类

当功能配置类生效的时候,会根据@EnableConfigurationProperties(RedisProperties.class) 声明,注入默认的属性配置类。

image.png

5)创建对应的类

Redis 功能配置里面会根据条件生成最终的 JedisConnectionFactory、RedisTemplate,并提供了默认的配置形式 @ConditionalOnMissingBean(name = "redisTemplate")

在实际使用的时候,如果我们在配置文件中自定义了一些配置,比如 Redis 的地址、端口号等等,注解 @ConditionalOnMissingBean(name = "redisTemplate") 会让默认配置被覆盖,从而使用我们自定义的配置。

@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
        RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
    RedisTemplate<Object, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    return template;
}

6)使用 RedisTemplate

至此,在启动的过程中,RedisTemplate 就已经被创建并配置好了,我们只需要在代码中注入就可以直接使用了,就像下面这样

@Autowired
private RedisTemplate redisTemplate;

写在后面

本文对 Spring Boot 的自动装配流程做了一个简要的分析,目的是让看官对 Spring Boot 的自动装配有一个清晰的了解,但本文远没有深入的原理的程度进行分析。

我的目的是让读者看阅读起来“不累”,哪怕是深入原理也不会一次写太多,这是我的写作风格,我相信每天积累一点点,菜鸟也可以变大神!

如果本文对你有帮助希望你能点个赞👍。