spring源码:@Import 注解

前言

根据这个名字我们不难猜的,就是导入一些信息, spring中能导入什么,无非就是导入一些类信息,进而让spring识别到转化成BeanDefinition 装入beanDefinitionMap中,这样一说好像和@Component @Service 等等没啥区别了,其实不然,这个@Import导入的类处理的比较前置,甚至处理一些BeanFactory一些信息,比如springboot中@EnableXXX 都是这么处理

接口信息

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration @Configuration}, {@link ImportSelector},
	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
	 */
	Class<?>[] value();

}

非常简单就一个属性value, 里面是方Class 信息

解析Import接口时机

在这里插入图片描述

源码分析

org.springframework.context.annotation.ConfigurationClassParser#processImports

org.springframework.context.annotation.ConfigurationClassParser#processImports
/**
	 * 处理我们的@Import注解,注意我们的@Import注解传入的参数,可能有三种类型
	 * 1,传入一个class类,直接解析
	 * 2,传入一个registrar,需要解析这个registrar
	 * 3,传入一个ImporterSelector,这时候会去解析ImporterSelector的实现方法中返回的数组的class
	 *
	 */
	private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
				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);
						}
						if (selector instanceof DeferredImportSelector) {
							//如果为延迟导入处理则加入集合当中
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							///根据ImportSelector方法的返回值来进行递归操作
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
						// Candidate class is an ImportBeanDefinitionRegistrar ->
						// delegate to it to register additional bean definitions
						Class<?> candidateClass = candidate.loadClass();
						//获取实例对象,如果同时实现Aware接口此时触发aware中相关接口
						ImportBeanDefinitionRegistrar registrar =
								ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
										this.environment, this.resourceLoader, this.registry);
						//添加的一个和Importselector方式不同的map中,sprig对两种方式传入的类注册方式不同
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
						// process it as an @Configuration class
						// 如果当前的类既不是ImportSelector也不是ImportBeanDefinitionRegistar就进行@Configuration的解析处理
						this.importStack.registerImport(
								currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
						processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
					}
				}
			}
			catch (BeanDefinitionStoreException ex) {
				throw ex;
			}
			catch (Throwable ex) {
				throw new BeanDefinitionStoreException(
						"Failed to process import candidates for configuration class [" +
						configClass.getMetadata().getClassName() + "]", ex);
			}
			finally {
				this.importStack.pop();
			}
		}
	}

总结

从上面的源码中我们发现@Import 导入的信息分3类:
a)import一个普通类:@Import(A.class)
b)import一个Registrar:比如我们的aop @Import(AspectJAutoProxyRegistrar.class)
c)import一个ImportSelector:具体妙用见Spring源码之 ImportSelector

@Component,@Service,@Repository这这样注入spring和@Import 处理时机不同:

至于spring在什么时候处理的呢,我大致叙述一下,有兴趣的可以自己去研究下spring源码:
对于普通类,spring在doScan的时候,就将扫描出来的java类转换成我们的BeanDefinition,然后放入一个BeanDefinitionMap中去
对于@import的三种情况,处理就在我们的ConfigurationClassPostProcessor(该类是我们BeanDefinitionRegistryPostProcessor后置处理器的一个实现,同时这也是我们spring内部自己维护的唯一实现类(排除内部类)),具体处理import的核心代码如下,if-else 很容易可以看出spring对于我们import三种类型的处理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值