@Import注解提供了三种用法

1、@Import一个普通类 spring会将该类加载到spring容器中

2、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition

3、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中

接下来挨个测试:

场景一  import普通类

1. 自定义一个类 没有任何注解

public class MyClass {
	
	public void test() {
		System.out.println("test方法");
	}
}

2. 写一个importConfig类 import这个myClass类

@Import(MyClass.class)
public class ImportConfig {
	
}

 3. 通过AnnotationConfigApplicationContext 初始化spring容器 调用test方法 看输出, MyClass类被加载进了 spring容器当中

场景二、 实现ImportBeanDefinitionRegistrar

 1. 创建一个普通类MyClassRegistry

public class MyClassRegistry {
	
	public void test() {
		System.out.println("MyClassRegistry test方法");
	}
}

 2. 创建MyImportRegistry 实现ImportBeanDefinitionRegistrar接口 注册我们定义的普通类MyClassRegistry

public class MyImportRegistry implements ImportBeanDefinitionRegistrar{
	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		RootBeanDefinition bd = new RootBeanDefinition();
		bd.setBeanClass(MyClassRegistry.class);
		registry.registerBeanDefinition("myClassRegistry", bd);
	}
}

 3. import该类

@Import(MyImportRegistry.class)
public class ImportConfig {
	
}

 4. 执行main方法 查看输出

 

 场景三、 实现ImportSelector

  1. 创建一个普通类MyClassImport 

public class MyClassImport {
	
	public void test() {
		System.out.println("MyClassImport test方法");
	}
}

   2. 创建MyImportSelector实现ImportSelector接口 注册我们定义的普通类MyClassImport

public class MyImportSelector implements ImportSelector {

	@Override
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		return new String[] {MyClassImport.class.getName()};
	}

}

  3. import该类

@Import(MyImportSelector.class)
public class ImportConfig {
	
}

  4. 执行main方法 查看输出

场景二应用于spring-mybatis当中 扫描dao信息 生成代理类信息

场景三应用于springboot的自动装配当中 加载自动装配需要的类信息

源码分析:

org.springframework.context.annotation.ConfigurationClassParser.processImports(ConfigurationClass, SourceClass, Collection<SourceClass>, boolean)方法中 就是处理Import注解类引入的bd信息

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
			Collection<SourceClass> importCandidates, 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) {
					if (candidate.isAssignable(ImportSelector.class)) {//拿ImportSelector类
					
						Class<?> candidateClass = candidate.loadClass();//获得class信息
						ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
								this.environment, this.resourceLoader, this.registry);
						if (selector instanceof DeferredImportSelector) {//判断是否是延迟加载的ImportSelector对象
							this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
						}
						else {
							String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());//拿到selectImports方法返回的类信息
							Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames);
							processImports(configClass, currentSourceClass, importSourceClasses, false);
						}
					}
					else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {//扫描到类是继承ImportBeanDefinitionRegistrar 将配置类封装成ConfigurationClass类 后续会处理
						// 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());
						processConfigurationClass(candidate.asConfigClass(configClass));
					}
				}
			}
			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();
			}
		}
	}

org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(Set<ConfigurationClass>)

在loadBeanDefinitions中会调用loadBeanDefinitionsFromRegistrars方法  最终执行到实现类的registerBeanDefinitions方法  继而将自定义的bd注册到beanDefinitionMap当中 交给spring去初始化

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐