spring源码之@Import
2021/6/11 20:23:00
本文主要是介绍spring源码之@Import,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
@Import注解的作用为解析指定的class类,如果是简单的java类就直接作为一个bean放入容器中,如果是@Configuration就正常当做配置类解析,
如果实现了ImportSelector接口,就会调用selectImports接口方法将返回的字符串数组对应的class加载进容器并递归解析;
如果实现了ImportBeanDefinitionRegistrar接口,就会调用registerBeanDefinitions接口方法,通过这种方式可以自由的注册Bean到IOC容器中,mybatis的MapperScan注解就是通过这种方式扩展的
org.mybatis.spring.annotation.MapperScannerRegistrar,关于mybatis扩展的详细内容单独写一篇博文
下面看下spring代码是怎么处理这段逻辑的,入口为下方这个BeanDefinitionRegistryPostProcessor:
org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
BeanDefinitionRegistryPostProcessor的调用入口在org.springframework.context.support.AbstractApplicationContext#refresh这里,详细的可以参考spring启动过程那篇博文:
该后处理bean能处理哪些bean?org.springframework.context.annotation.ConfigurationClassUtils#checkConfigurationClassCandidate给出了答案
首先是要有Configuration注解,其次是看org.springframework.context.annotation.ConfigurationClassUtils#isConfigurationCandidate
是的,就是处理有Configuration注解,并且至少有这四个注解中的一个Component、ComponentScan、Import、ImportResource
回到org.springframework.context.annotation.ConfigurationClassPostProcessor#processConfigBeanDefinitions
解析的核心方法为org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass
ComponentScan注解的处理:
其他注解的处理:
重点看到@Import注解的处理逻辑:
for (SourceClass candidate : importCandidates) { // ImportSelector注解处理逻辑 if (candidate.isAssignable(ImportSelector.class)) { // Candidate class is an ImportSelector -> delegate to it to determine imports Class<?> candidateClass = candidate.loadClass(); ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry); Predicate<String> selectorFilter = selector.getExclusionFilter(); if (selectorFilter != null) { exclusionFilter = exclusionFilter.or(selectorFilter); } // 实现DeferredImportSelector接口的selector暂存放到最后处理,因为实现该接口的类通常会带有 @Conditional注解,只有等到其他所有 // bean都加载完了才能确定是否要添加该bean,典型的就是springboot的自动装配selector:org.springframework.boot.autoconfigure.AutoConfigurationImportSelector // 典型的注解如ConditionalOnMissingBean if (selector instanceof DeferredImportSelector) { this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector); } else { // 普通的ImportSelector就直接调用selectImports返回字符串数组,并递归解析这些class String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata()); Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter); processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false); } } // 实现ImportBeanDefinitionRegistrar接口的selector会先实例化并把实例放入到configClass的importBeanDefinitionRegistrars中暂存 // parse完回到后处理bean中,下方的ConfigurationClassBeanDefinitionReader会丛中注册beanDefinition else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) { // Candidate class is an ImportBeanDefinitionRegistrar -> // delegate to it to register additional bean definitions Class<?> candidateClass = candidate.loadClass(); ImportBeanDefinitionRegistrar registrar = ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry); configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata()); } else { // 这里的英文注释很清楚了吧,都不是上面两种情况的话直接当做@Configuration处理 // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar -> // process it as an @Configuration class this.importStack.registerImport( currentSourceClass.getMetadata(), candidate.getMetadata().getClassName()); processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter); } }
org.springframework.context.annotation.ConfigurationClassParser#processConfigurationClass最后会把当前configClass放入集合
parse完回到后处理bean:ConfigurationClassPostProcessor
下面看下reader方法:
核心方法org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader#loadBeanDefinitionsForConfigurationClass
至此,@Import方式扩展注册beanDefinition就基本都清晰了。
这篇关于spring源码之@Import的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-31全网首发第二弹!软考2024年5月《软件设计师》真题+解析+答案!(11-20题)
- 2024-05-31全网首发!软考2024年5月《软件设计师》真题+解析+答案!(21-30题)
- 2024-05-30【Java】百万数据excel导出功能如何实现
- 2024-05-30我们小公司,哪像华为一样,用得上IPD(集成产品开发)?
- 2024-05-30java excel上传--poi
- 2024-05-30安装笔记本应用商店的pycharm,再安排pandas等模块,说是没有打包工具?
- 2024-05-29java11新特性
- 2024-05-29哪些无用敏捷指标正在破坏敏捷转型?
- 2024-05-29鸿蒙原生应用再新丁!新华社 入局鸿蒙
- 2024-05-29设计模式 之 迭代器模式(Iterator)