SpringBoot 的自动装配原理

@SpringBootApplication 注解。它可以看作是 @EnableAutoConfiguraion@ComponentScan@Configuration 注解的集合。

  • @EnableAutoConfiguraion:启动 SpringBoot 的自动配置机制。
  • @ComponentScan:扫描被 @Component@Service@Controller)注解的 Bean,注解默认会扫描该类所在包下的所有类。
  • @Configuration:允许在上下文注册额外的 Bean 或导入其他配置类。

@EnableAutoConfiguraion注解通过 Spring 提供的 @Import 注解导入了 AutoConfigurationImportSelector 类( @Import 注解可以导入配置类或者 Bean 到当前类)

AutoConfigurationImportSelector 类中 getCandidateConfigurations 方法会将所有自动配置类的信息以 List 的形式返回,作为 Bean 被 Spring 容器管理。

@Conditional 注解。@ConditionalOnClass(指定的类必须存在于类路径下)、@ConditionalOnBean(容器中必须含有指定的 Bean)来根据条件决定是否启用某个配置。

@EnableAutoConfiguration 是实现自动装配的重要注解,我们以这个注解入手。

@EnableAutoConfiguration:实现自动装配的核心注解

EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage //作用:将main包下的所有组件注册到容器中
@Import({AutoConfigurationImportSelector.class}) //加载自动装配类 xxxAutoconfiguration
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

Class<?>[] exclude() default {};

String[] excludeName() default {};
}

AutoConfigurationImportSelector:加载自动装配类

AutoConfigurationImportSelector类的继承体系如下:

1
2
3
4
5
6
7
8
9
10
11
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {

}

public interface DeferredImportSelector extends ImportSelector {

}

public interface ImportSelector {
String[] selectImports(AnnotationMetadata var1);
}

可以看出,AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法,该方法主要用于获取所有符合条件的类的全限定类名,这些类需要被加载到 IoC 容器中

1
2
3
4
5
6
7
8
9
10
11
12
13
private static final String[] NO_IMPORTS = new String[0];

public String[] selectImports(AnnotationMetadata annotationMetadata) {
// <1>.判断自动装配开关是否打开
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
//<2>.获取所有需要装配的bean
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}

这里我们需要重点关注一下getAutoConfigurationEntry()方法,这个方法主要负责加载自动配置类的。

该方法调用链如下:

SpringBoot自动装配调用链

AutoConfigurationImportSelector.getAutoConfigurationEntry(AnnotationMetadata)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
// 判断自动装配开关是否打开。
// 默认spring.boot.enableautoconfiguration=true
// 可在 application.properties 或 application.yml 中设置
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
// 用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
// 获取需要自动装配的所有配置类
// 读取META-INF/spring.factories
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
// @ConditionalOnXXX 中的所有条件都满足,该类才会生效
configurations = this.removeDuplicates(configurations);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}

Spring Boot的自动配置原理主要基于以下几个核心机制:

  1. 条件化配置(Conditional Configuration):Spring Boot使用条件注解(如@ConditionalOnClass@ConditionalOnProperty等)来根据条件决定是否启用某个配置。这些条件注解可以应用于配置类、Bean声明、方法等地方,通过判断条件的真假来确定是否生效。
  2. 自动扫描(Component Scanning):Spring Boot会自动扫描应用的类路径,寻找特定的注解标记的Bean或组件,例如@Component@Service@Repository等。当发现这些注解时,Spring Boot会自动将它们注册为Bean,以供应用使用。
  3. Starter依赖(Starter Dependencies):Spring Boot的Starter依赖是一组预配置的依赖项,它们集成了特定功能模块的所有必需依赖。通过添加Starter依赖,Spring Boot能够自动配置和启用相应的功能。例如,使用spring-boot-starter-web依赖可以启用Web开发相关的自动配置。
  4. 自动装配(Auto-Configuration):Spring Boot提供了一系列的自动配置类(以AutoConfiguration结尾),这些类定义了在特定条件下应该配置哪些Bean和组件。当条件满足时,Spring Boot会自动加载这些自动配置类,并将相关的Bean注入到应用的上下文中。
  5. 配置文件(Configuration Properties):Spring Boot通过读取应用的配置文件(如application.propertiesapplication.yml)来获取配置参数。这些配置参数可以用于自动配置的条件判断或配置属性的注入。

通过上述机制,Spring Boot能够根据应用的依赖、配置和条件,自动进行相应的配置和初始化工作,从而简化了开发者的工作,提高了开发效率。开发者也可以通过自定义配置、条件注解和自动配置类等方式,扩展和定制Spring Boot的自动配置行为。