@Import注解的使用及原理解析

@Import注解的使用即原理解析

作用

动态的注入Bean

1.@Import

使用

public class Demo {
}
@Import(Demo.class)
@Configuration
public class ImportDemo {
}

原理解析

ConfigurationClassParser.class


ioc 之后执行
protected final SourceClass doProcessConfigurationClass({
  ............................
 processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
}

获取@Import 注解需要注入的类

 
private Set<SourceClass> getImports(SourceClass sourceClass) throws IOException {
		Set<SourceClass> imports = new LinkedHashSet<>();
		Set<SourceClass> visited = new LinkedHashSet<>();
		collectImports(sourceClass, imports, visited);
		return imports;
	}

将@import 注解需要注入的类收集

	private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
			throws IOException {

		if (visited.add(sourceClass)) {
			for (SourceClass annotation : sourceClass.getAnnotations()) {
				String annName = annotation.getMetadata().getClassName();
				if (!annName.equals(Import.class.getName())) {
					collectImports(annotation, imports, visited);
				}
			}
            //收集@ Import注解中需要注入的类
			imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
		}
	}

选择合适的注入方式

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
			boolean checkForCircularImports) {
         //如果需要注入的类为null直接返回
		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);
							processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
						}
					}
                    //如果实现了 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);
						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());
						//ioc
                        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();
			}
		}
	}

parse 结束之后会将需要注入的类存放在 configurationClasses 当中

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
      .........

		this.configurationClasses.put(configClass, configClass);
	}

进行注入

	/**
	 * Build and validate a configuration model based on the registry of
	 * {@link Configuration} classes.
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
            ........
			parser.parse(candidates);
            ................. 
			this.reader.loadBeanDefinitions(configClasses);
		     ................

	}
	public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
		TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
		//遍历需要注入的类
        for (ConfigurationClass configClass : configurationModel) {
			loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
		}
	}
	private void loadBeanDefinitionsForConfigurationClass(
			ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {

		if (trackedConditionEvaluator.shouldSkip(configClass)) {
			String beanName = configClass.getBeanName();
			if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
				this.registry.removeBeanDefinition(beanName);
			}
			this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
			return;
		}
        
		if (configClass.isImported()) {
			registerBeanDefinitionForImportedConfigurationClass(configClass);
		}
		for (BeanMethod beanMethod : configClass.getBeanMethods()) {
			loadBeanDefinitionsForBeanMethod(beanMethod);
		}
         //装载@ImportResource 注解收集的资源
		loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
		loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
	}
private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
		//获取 Metadata 信息
        AnnotationMetadata metadata = configClass.getMetadata();
		//包装成 BeanDefinition 
        AnnotatedGenericBeanDefinition configBeanDef = new AnnotatedGenericBeanDefinition(metadata);

		ScopeMetadata scopeMetadata = scopeMetadataResolver.resolveScopeMetadata(configBeanDef);
		configBeanDef.setScope(scopeMetadata.getScopeName());
		String configBeanName = this.importBeanNameGenerator.generateBeanName(configBeanDef, this.registry);
		AnnotationConfigUtils.processCommonDefinitionAnnotations(configBeanDef, metadata);

		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(configBeanDef, configBeanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		//注册
        this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition());
		configClass.setBeanName(configBeanName);

		if (logger.isTraceEnabled()) {
			logger.trace("Registered bean definition for imported class '" + configBeanName + "'");
		}
	}

2.实现ImportSelector接口

使用

public class SelfImportSelector  implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //需要注入的类
        return new String[]{"com.alipay.model.imports.Demo"};
    }
}
@Import(SelfImportSelector.class)
@Configuration
public class ImportDemo {
}

原理

protected final SourceClass doProcessConfigurationClass(
			ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
			throws IOException {
      ......
	// Process any @Import annotations
		processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
      ......
}
private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
							Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
							boolean checkForCircularImports) {
	.......
		for (SourceClass candidate : importCandidates) {
			  //如果是实现了 ImportSelector接口的类
			if (candidate.isAssignable(ImportSelector.class)) {
				// Candidate class is an ImportSelector -> delegate to it to determine imports
				//获取自定义实现了 ImportSelector接口的类
				Class<?> candidateClass = candidate.loadClass();
				
				ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
		        //获取 getExclusionFilter 接口返回的数据																	   this.environment, this.resourceLoader, this.registry);
				Predicate<String> selectorFilter = selector.getExclusionFilter();
				if (selectorFilter != null) {
					exclusionFilter = exclusionFilter.or(selectorFilter);
				}
			    //如果是 DeferredImportSelector																   
				if (selector instanceof DeferredImportSelector) {
					//进行自动装配
					this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
				}
				else {
					//获取 selectImports 方法返回的数组数据
					String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
					//根据定义的需要注入的类  拿到需要注入的实例
					Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
					//再次调用 processImports  最后将实例装入 configurationClasses 然后进行注入
					processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
				}
			}
			.....
			}
}

最后将实例装入 configurationClasses 在 parse 方法调用完之后 然后进行注入 注入方式参考上面@Import的

3.实现ImportBeanDefinitionRegistrar接口

应用

public class MyImportBeanDefinitionRegistrar  implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        //指定bean定义信息(包括bean的类型、作用域...)
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Demo.class);
        //注册一个bean指定bean名字(id)
        registry.registerBeanDefinition("Demo1111",rootBeanDefinition);

    }


}
@Import(MyImportBeanDefinitionRegistrar.class)
@Configuration
public class ImportDemo {
}

原理

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
							Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
							boolean checkForCircularImports) {
	..........
	else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
		// Candidate class is an ImportBeanDefinitionRegistrar ->
		// delegate to it to register additional bean definitions
		//获取实现了 ImportBeanDefinitionRegistrar 注解的类
		Class<?> candidateClass = candidate.loadClass();
        //进行设置类的信息   
		ImportBeanDefinitionRegistrar registrar =
			ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
												 this.environment, this.resourceLoader, this.registry);
		//将需要注入的数据存储到一个map中 存在 标注了@Import注解的类的实例信息里
		configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
	}
	..........
}
public void addImportBeanDefinitionRegistrar(ImportBeanDefinitionRegistrar registrar, AnnotationMetadata importingClassMetadata) {
		this.importBeanDefinitionRegistrars.put(registrar, importingClassMetadata);
	}

在 parse 方法调用完之后 然后进行注入 注入方式参考上面@Import的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值