JAVA面试题分享四十:Spring Boot 中自装配机制的原理?

什么是SpringBoot自动装配

所谓的“SpringBoot自动装配”就是指:通过注解和一些简单的配置就能将某些组件载入Spring容器环境中,便于使用。 比如,很多spring-boot-starter组件只要简单引入,然后在SpringBoot的配置文件application.propertiesapplication.yml中添加对应的参数配置就可以使用了,非常方便。 实际上,“自动装配”机制是Spring Boot定义的一个规范:SpringBoot在启动时会扫描外部引用jar包中的META-INF/spring.factories文件,将文件中配置的类信息加载到Spring容器,并执行类中定义的各种操作。对于外部jar来说,只需要按照SpringBoot定义的标准,就能将自己的功能装置进SpringBoot。

那么,这种“自动装配”机制具体是如何实现的呢?

SpringBoot自动装配实现机制

其实,这一切都要从Spring Boot的核心注解@SpringBootApplication说起。

// 注解@SpringBootApplication的定义
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {}

// 注解@SpringBootConfiguration的定义,本质上就是@Configuration注解的包装
@Configuration
public @interface SpringBootConfiguration {}

// 注解@EnableAutoConfiguration的定义
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

如上,从注解@SpringBootApplication的定义来看,本质上它是@ConfigurationEnableAutoConfiguration@ComponentScan这三个注解的组合,它们的含义分别是:

  • @Configuration:用于在上下文中注册额外的Bean或导入其他配置类
  • @EnableAutoConfiguration:启用Spring Boot的自动装配机制
  • @ComponentScan:扫描被@Component@Service@Controller等注解的Bean,默认会扫描启动类所在包及其子包下的所有类,可以自定义不扫描某些类

所以,注解@EnableAutoConfiguration才是实现Spring Boot自动装配的关键。

在注解@EnableAutoConfiguration中通过@Import导入了AutoConfigurationImportSelector类,在这个类中真正实现了从外部jar包的META-INF/spring.factories文件中读取配置的类信息。 具体来说,是在getCandidateConfigurations()方法中实现读取配置类的。

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 调用SpringFactoriesLoader.loadFactoryNames()方法从文件META-INF/spring.factories中读取配置信息类
    List<String> configurations = new ArrayList<>(
            SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()));
    ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add);
    Assert.notEmpty(configurations,
            "No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}

那么,通过AutoConfigurationImportSelector读取的配置信息类在哪里使用了呢? 实际上,这个需要跟SpringBoot的启动流程关联起来,经过代码追踪可以知道,调用AutoConfigurationImportSelector.getCandidateConfigurations()方法读取外部文件中的配置类这个操作是在IoC容器的refresh()方法中触发的。也就是说,在IoC容器启动的时候通过调用getCandidateConfigurations()方法把外部文件中指定的类读取进来,然后再使用反射机制将它们实例化成为Bean对象载入到IoC容器中。 SpringBoot的启动时序图如下所示:

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值