Spring Boot的自动装配(Auto Configuration)是其核心特性之一,它允许开发者在项目中以最少的配置运行 Spring 应用。这一特性使得开发者无需手动配置大量的 Bean 和组件,Spring Boot 会根据项目中的依赖和应用场景,自动配置合适的 Spring 组件。
什么是自动装配?
未使用自动装配之前
在传统的 springmvc 项目中,当我们需要使用 mvc 模块、mysql 数据模块、redis 缓存模块的时候。我们需要导入依赖的 jar,然后在 spring 的配置文件中配置 dataSource、sqlsessionFactory、internalResourceViewResolver(视图解析器)、multipartResolver(文件上传)、事务管理器等模块。把这些我们需要的模块变成 bean,给 spring 管理。
SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories 文件,将文件中配置的类型信息加载到 Spring 容器(此处涉及到 JVM 类加载机制与 Spring 的容器知识),并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot。
在了解自动装配之前,我们首先来回顾一下以前的 springMVC 项目。在 MVC 中我们使用容器依赖的bean 的时候需要在 xml 中配置声明才能使用,比如 springmvc 中的以下配置。
在web.xml中配置 dispatcherServlet 和 filter

没用使用自动装配之前,这些庞杂的web配置是每一个项目必须的。我们首先在pom中引入相关的jar。然后再xml中一遍一遍的配置这些东西。 十分复杂低效。
初步了解自动装配
springboot 是一个脚手架工具,约定大于配置。我们只需要按照 springboot 的规范来开发,就能减少很多配置,当需要开发 web 项目的时候。
第一步:引入web 包的 starter 启动器。这个包就包含了 web 的所需的主要功能,同时能导入springweb 相关的依赖 jar。比如spring,springmvc 的包和 tomcat 的包。点击 pom 可查询。
<!--springboot的web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
第二步: 我们启动springboot项目之后,就能看到所有的bean。这些bean在容器加载的时候就会把bean自动加载进来。
@SpringBootApplication(scanBasePackages = "com.thits")
@ImportResource(value = "bean.xml") //装配xml文件配置的bean
public class SpringBoot1Application {
public static void main(String[] args) {
//返回ioc容器
ConfigurableApplicationContext run = SpringApplication.run(SpringBoot1Application.class, args);
//获取容器中的所有bean
String[] beanDefinitionNames = run.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println("bean的名字:"+beanDefinitionName);
}
}
}
截图可以看到控制台的各种 bean 已经被 spring 容器管理了。 比如 multipartResolver、DispatcherServlet、视图解析器、事务管理器等。我们就可以直接使用了,不需要在 xml 中配置这些东西了。

自动装配、按需加载
在启动类中有一个注解就是 @SpringBootApplication,他有三个子注解,子注解又有其他的注解,搞清楚这些注解的意思就能理解自动装配了。
Spring Boot应用程序的入口通常带有@SpringBootApplication注解。这个注解是一个组合注解,包含了@Configuration、@EnableAutoConfiguration和@ComponentScan。
@SpringBootApplication(有三个子注解)@SpringBootConfiguration@Configuaration
@EnableAutoConfiguration(开启自动注入:有两个子注解)@AutoConfigurationPackage(自动配置包:有一个子注解,import)@Import({Registrar.class})
@Import({AutoConfigurationImportSelector.class})
@ComponentScan(组件扫描 作用:包扫描项目包路径)
其中,@EnableAutoConfiguration是自动装配的关键,它启动了自动装配机制。
@Import({Registrar.class}) 注解的源码
/**
* {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
}
@Override
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new PackageImports(metadata));
}
}
@Import({Registrar.class}) 源码的作用就是:主启动类注册到容器,也就是 main 方法所在的包下边,将所有的我们自己的代码中的配置注入的 bean 容器。
通过实现 ImportBeanDefinitionRegistrar,向 Spring 容器中添加 Bean 定义
@Import({AutoConfigurationImportSelector.class}) 注解的源码
源码的第一步就是实现 ImportSelector 接口的 ImportSelector 方法,根据类的全部限定名字把类注入到容器(参见 import 注解的用法),注入了那些类呢?接着看源码

此处源码是获取自动装配的配置类。获取了138个,在哪里获取接着看。
这里的代码就能看出来去哪里加载了这些自动装配的类,在factories文件中。

我们查看 autoconfigure 的 jar 下边的 factories 文件就能看到这些指定的自动装配类全类名了。

自动装配含义
通过@SpringBootApplication注解的两个Import子注解 ,把spring-boot-autoconfigure-2.6.7.jar和其他包的spring.factories 文件中,EnableAutoConfiguration配置的所有类都装配到spring容器中了。
自动装配扩展原理(Condition按需加载)
springboot自动装配的扩展:两个疑难问题讲解:
问题1:
我们查看spring.factories中有当前版本支持的所有配置类,这些配置类都会注入bean吗?
答:并不是,之后我们需要导入相对的jar包,这个类是真是存在的,然后才可以自动装配这些bean。
举例说明:在spring.factories中有很多配置类,我们截取这几个来说明

举例1:我们没有配置 DispatcherServlet,但是会通过自动装配,层层判断来自动创建出DispatcherServlet

举例2:我们Aop的案例

问题2
在spring 的 IOC 注入了这些138个配置类,我们怎么使用?
答:通过配置使用,约定大约配置。
比如我们使用文件上传。我们怎么知道配置文件上传的文件大小、文件路径等信息。在源码中我们可以看到怎么使用。约定大于配置
springboot默认创建StandardServletMultipartResolver,在源码中如下
文件上传约定大约配置,我们都知道 ConfigurationProperties 注解的作用是绑定配置文件的值。这里就是约定大于配置。我们只需要按照约定来就行了


自动装配总结:
1:springboot 默认加载 spring.factories 中指定的所有 AutoConfiguration 。
2:根据这些 AutoConfiguration 的源码,在里边的条件 @conditional 判断是否真正的使用这些类。
3:导入的对应 jar 话就使用这些类,并且在绑定的 Properties 根据前缀中指定,然后在配置文件中配置属性
这就是自动装配了。