SpringBoot - 原理 - 初探自动装配

SpringBoot - 原理 - 初探自动装配,第1张

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 标注的配置类进行导入,但通过翻看源码注释我们可以发现他还有其他的功能,就是导入相应的 importSelector 和 importBeanDefinitionRegistrar:

         跳转到 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 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 包下的该文件,至此得解。

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5712276.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)