SpringBoot2和SpringBoot3的自动配置原理大致相同,只是存放我们导入的starter中的配置类的信息的文件由对应starter的jar包下的META-INF/spring.factories文件变成了META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件。
此外,本文只是简单概述了一下SpringBoot自动配置的原理,不是很详细,做一个大致的了解,如果想要了解的更深入,可以看一下我曾经在网上看到的这几篇文章。
springboot2的自动配置原理
springboot3的自动配置原理
启动类文件中的main方法
要谈 SpringBoot 的自动装配,肯定离不开下面这段代码。
先来看看这段代码:
ConfigurableApplicationContext run = SpringApplication.run(AppRunApplication.class, args);
这段代码的作用是启动 SpringBoot 应用程序,并返回一个 ConfigurableApplicationContext 对象的实例。
SpringApplication.run() 方法返回的是 ConfigurableApplicationContext 类型的对象,表示 Spring 应用程序的上下文。这个上下文保存了Spring 容器中所有 bean 的引用,对于应用程序中的其他组件来说,这个上下文就是一个全局共享的容器。
SpringApplication.run(AppRunApplication.class, args) 语句的意义是基于 AppRunApplication 这个类启动 SpringBoot 应用程序,并将命令行参数传递给应用程序。运行这个语句后,Spring会自动进行应用程序的初始化工作,包括创建ApplicationContext、注册所有的bean定义、启动嵌入式Web容器、加载应用程序的配置文件等。
此外,通过这个方法还可以获取到 ConfigurableApplicationContext 的实例,使用这个对象可以进一步控制应用程序的运行,如手动关闭应用程序、获取应用程序的环境变量、添加自定义的bean等。
这个 run 其实 可以简单地理解为 Spring 的 IOC 容器,SpringBoot 启动时会自动帮我们配置程序运行需要的使用的 Bean 对象放到 IOC 容器中,我们在其他类需要使用时只需要使用 @Autowire 或者 @Resource 注解进行依赖注入即可。
举例:
我们在启动类中,创建了一个 Test 类,然后声明了一个 Bean 方法,它的作用就是返回一个 Test 类,然后我们进行断点调试。
我们通过 run 拿到了 Test 的 Bean 实例
如果我们试图获取一个没有使用 Bean 方法注册的类,就会抛出异常。
自动配置
每次启动一个springboot程序都要通过主配置类来启动,这个主配置类上放了一个注解@SpringBootApplication
,此注解意为:标注在某个类上说明这个类是SpringBoot的主配置类,SpringBoot就应该运行这个类的main方法来启动SpringBoot应用,是我们研究的重点!
点进@SpringBootApplication
,发现是一个组合注解
@Target:用于指定注解的作用目标
@Retention:注解的生命周期
@Document:是否生成javaDoc文档
@Inherited:注解是否可以被继承
@ComponentScan:这个注解用于指定 Spring 扫描组件的基础包。Spring 会扫描指定包及其子包下的所有类,查找带有 @Component
及其派生注解(如 @Service
、@Repository
、@Controller
)的类,并将其注册为 Spring 的 bean。
@SpringBootConfiguration:这个注解是 @Configuration
注解的派生注解,用于标识一个类是 Spring Boot 的配置类。Spring Boot 会自动扫描这些配置类并加载其中的配置。
@EnableAutoConfiguration:这个注解用于启用 Spring Boot 的自动配置机制。它会根据项目的依赖和配置,自动配置 Spring 应用程序的 bean。
其中最核心的就是 @EnableAutoConfiguration 这个注解
@EnableAutoConfiguration
顾名思义:开启自动配置功能,点进去看一下
其中重点是@AutoConfigurationPackage 和 @Import({AutoConfigurationImportSelector.class})
@AutoConfigurationPackage
自动导入配置包
点进去查看源码
@Import 为spring的注解,导入一个配置文件,在springboot中给容器导入一个组件,而导入的组件由 AutoConfigurationPackages.class的内部类Registrar.class 执行逻辑来决定是如何导入的。
点进去查看源码
打断点进行调试,可以看到metadata显示为当前启动类所在的包名。
注:Registrar实现了ImportBeanDefinitionRegistrar类,就可以被注解@Import导入到spring容器里。
结论
@AutoConfigurationPackage 就是将主配置类(@SpringBootApplication 标注的类)所在的包下面所有的组件都扫描注冊到 spring 容器中。
@Import({AutoConfigurationImportSelector.class})
AutoConfigurationImportSelector:开启自动配置类导包的选择器,即是有选择性的导入META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中符合条件的配置类(@ConditionalOnxxx注解),@EnableAutoConfiguration会自动的把上面文件里面写的所有自动配置类都导入进来。
结论
@Import(AutoConfigurationImportSelector.class):加载所有通过starter导入进来的自动配置类到spring容器中。
总结:
springboot的自动配置主要集中在@SpringBootApplication中的@EnableAutoConfiguration注解中,而@EnableAutoConfiguration注解又使用@AutoConfigurationPackage来导入启动类包下的配置类到spring容器,使用 @Import({AutoConfigurationImportSelector.class}) 导入*imports文件下符合@ConditionOnXXX的配置类到spring容器。