Spring Boot 的自动配置是如何实现的?

Spring Boot 自动配置的原理

SpringBoot 使用起来非常方便,核心就在于自动配置,接下来分析一下SpringBoot自动配置的实现原理。
(2.4.1)

@SpringBootApplication

这是 SpringBoot 主类上的注解,来看一下它的源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
	// .....
}

它由主要的三个注解:@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan 构成。

下面单独分析三个注解。

@SpringBootConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

与 @Configuration 功能相同:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类

@ComponentScan

扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。

@EnableAutoConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

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

    String[] excludeName() default {};
}

@Import({AutoConfigurationImportSelector.class}) 就是实现自动配置的关键。

通过 AutoConfigurationImportSelector@EnableAutoConfiguration 可以将符合条件的 @Configuration 配置类都加载到 IoC容器中。

那么配置类在哪?符合条件又是什么意思?

  1. 加载哪些配置类?
    AutoConfigurationImportSelector 有这样一个方法,在这里插入图片描述
    它会去查找**所有依赖的 jar 包(不止 spring-boot-autoconfigure-2.4.1.jar)**中的 META-INF/spring.factories。

这是 spring-boot-autoconfigure-2.4.1.jar 中的 spring.factories:在这里插入图片描述

从这些 spring.factories 中,加载 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的所有配置类到 List 中,
spring.factories文件里每一个xxxAutoConfiguration文件一般都会有下面的条件注解:

@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效

接下来会根据这些类的条件注解,决定哪些类是生效的类。

一个条件注解示例:
在这里插入图片描述

实例

准备 jar 包

目的:

  1. 验证 SpringBoot 的自动配置功能是否可以加载其他 jar 包下的 spring.factories.
  2. 是否加载 spring.factories 中的 key 不为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的配置类。

步骤:
创建一个工程,在 resources 目录下添加 META-INF/spring.factories,
在 spring.factories 中一个类的 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration,
另一个类的key 为 org.springframework.boot.diagnostics.FailureAnalyzer
一会儿打成 jar 包,导入到 SpringBoot 工程中。

在这里插入图片描述

导入 SpringBoot 工程验证

AutoConfigurationImportSelector 中打个断点,我们就能够看到 entity.PersonTest 已经被导入进来了。
在这里插入图片描述
根据以上结果,得出初步结论:

  1. SpringBoot 的自动配置功能可以加载其他 jar 包下的 META-INF/spring.factories.
  2. 只加载 spring.factories 中的 key 为 org.springframework.boot.autoconfigure.EnableAutoConfiguration 的配置类。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值