SpringBoot - 原理 - 初探自动装配

        众所周知 SpringBoot 集成了一系列的配置文件与配置类,旨在帮助开发者快速上手开发,做到 You can just run。本文将就 SpringBoot 如何实现自动装配 @SpringBootApplication 同级路径下所有 @Component 的注册与对应 `org.springframework.web.servlet.DispatcherServlet` 中 Controller 切面的填充做一简单的探寻。

@SpringBootApplication

        SpringBoot 的核心启动类兼具装配 bean 与加载注解配置的功能,这一点从注解自身构造不难得出(节选部分代码):

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {}

        其中,@ComponentScan 为包扫描注解,在这里配置了排除的扫描种类,而 @SpringBootConfiguration 展开来看仅为 @Configuration 标注的一子级配置注解,代表以 @SpringBootApplication 标注的类也同为注解配置类,Spring 将对其进行一系列的注解配置解析(以下为 @SpringBootConfiguration 注解部分)。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
@Indexed
public @interface SpringBootConfiguration {}

@EnableAutoConfiguration

        顾名思义,我们不难猜测到使用这个注解标注即会触发自动装配的功能,我们先展开看一下它的注解结构:

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

自动装配包 - @AutoConfigurationPackage

        一看名字就可以得知,此注解是为了自动装配对应配置类的包路径而存在,我们展开看一下 @AutoConfigurationPackage 的内容

@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {}

        @Import 注解想必大家都非常熟悉,我们在 SpringMVC 中常使用它对 @Configuration 标注的配置类进行导入,但通过翻看源码注释我们可以发现他还有其他的功能,就是导入相应的 ImportSelectorImportBeanDefinitionRegistrar:

         跳转到 AutoConfigurationPackages.Registrar,我们不难发现这个内部类实现了 ImportBeanDefinitionRegistrar,该内部类以注解元数据(Annotationdata)Bean 注册实现类(BeanDefinitionRegistry,为一个接口,其实现类有常见的诸如 接口配置上下文加载器 AnnotationConfigApplicationContext 与 Xml 配置上下文加载器 XmlServletWebServerApplicationContext)解析注册了被扫描的包(Package)对象,实现了对启动类下包的自动装配:

	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));
		}

	}

自动装配 bean - @Import(AutoConfigurationImportSelector.class)

        AutoConfigurationImportSelector 这个类实现了 DeferredImportSelector 接口,即为上述 @Import 支持配置的 ImportSelector 接口的子类,这也是该实现类能被配置进 @Import 的根本原因。

        阅读源码,我们不难发现 AutoConfigurationImportSelector#process 这个方法,查看对应的接口方法我们可以得知该方法的作用是处理导入的 @Configuration 标注类的接口元数据(AnnotationMetadata)。那么在这个方法中,理应存在我们要找寻的自动装配的具体实现。

         查看实现类方法,我们可以看到以下一行获取自动配置条目(AutoConfigurationEntry)的内部方法:

         转到对应方法,我们不难在其中发现这样一行所谓 获取候选配置文件——即自动装配默认配置的方法 getCandidateConfigurations。在获取配置之后注册对应的加载事件(fireAutoConfigurationImportEvents)即是全部自动装配 bean 的流程。

思考

        至此,自动装配的逻辑实现便告一段落了,但我们仍有疑问——默认配置类在哪?带着这个疑问,我们点开了 getCandidateConfigurations 方法,发现真正的答案还得去 SpringFactoriesLoader 中寻找:

        跳转到 SpringFactoriesLoader#loadFactoryNames,查看方法注解我们得知,所有定义的默认工厂实现都在  "META-INF/spring.factories" 这个文件中配置,找到 spring-boot-autoconfiguration 包下的该文件,至此得解。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值