Sping 之 @Import

以下都是基于spring-5.2.8,之前的版本可能有所不同

Import 是spring中的一个注解,可以用来导入需要实例化的类,把这些类加入spring容器

而且通过Import导入进来的类是可以获取到父类上面的注解的信息,当然父类必须要先加入spring管理这个注解能起作用,这个注解是作用于类,接口上面的。

@Component
@Import({DeferredImportSelectorDemo.class,SelectImportDemo.class,AwareBean.class})
public class ImportBean {
}

 Improt注解使用也是很简单的,只需要在注解里面加上需要实例化的类就行了,当然Import进来的类也可以实现一些接口。

ImportSelector,ImportBeanDefinitionRegistrar两个接口是比较特殊的接口,实现这两个接口的类必须是通过Import导入的,这两个接口的方法才会被调用。

 selectImports 方法 入参是导入类的信息,返回值是String数组,数组里面是需要实例化的类的完整限定名  Dome.class.getName()

public class SelectImportDome implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        MergedAnnotations annotations = importingClassMetadata.getAnnotations();
        MergedAnnotation<EnableAspectJAutoProxy> eas = annotations.get(EnableAspectJAutoProxy.class);

        Object proxyTargetClass = eas.getValue("proxyTargetClass").get();
        //类的完整限定名,
        return new String[]{Dome.class.getName()};
    }
}

@Improt注解是由 ConfigurationClassPostProcessor 处理的 ,这个类实现了 BeanDefinitionRegistryPostProcessor 在spring容器初始的时候会 调用 postProcessBeanDefinitionRegistry ,postProcessBeanFactory这个两个方法

postProcessBeanDefinitionRegistry方法会收集注解,包装注册beanDefinition

这个是具体处理@Import注解的方法

具体方法代码

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {

		//如果没有@Import注解直接返回,不处理
		if (importCandidates.isEmpty()) {
			return;
		}

		if (checkForCircularImports && isChainedImportOnStack(configClass)) {
			this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
		}
		else {
			this.importStack.push(configClass);
			try {
				//循环类上面的每一个@Import
				for (SourceClass candidate : importCandidates) {
					//如果Import进来的是一个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类型
						if (selector instanceof DeferredImportSelector) {
							//比较复杂,springboot中自动配置用到了
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							//在这里调用selectImports方法,返回所有的需要import到spring容器的beanName
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
							//递归处理,有可能import进来的类又有@Import注解
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
					//如果Import进来的是一个ImportBeanDefinitionRegistrar类型
					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);
						//加入到importBeanDefinitionRegistrars容器中,这里还没有调用registerBeanDefinitions
						configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
					}
					else {
						// 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);
					}
				}
			}
			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();
			}
		}
	}

1. Import 引入没有实现ImportSelector,ImportBeanDefinitionRegistrar接口的类会直接解析这个类

2.  1).如果是实现了ImportSelector 接口的类 就会反射实例化,然后调用selectImports方法

      2).如果是实现了DeferredImportSelector 接口,会调到 DeferredImportSelectorGrouping里面的selectImports方法

其实获取方式还是ImportSelector 的selectImports

DeferredImportSelectorGrouping 也可以是自己实现的

 如果没有自己实现就是走默认的

3. 实现了ImportBeanDefinitionRegistrar 接口的,会先加入importBeanDefinitionRegistrars map里面,然后处理

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值