@Import注解提供了三种用法
1、@Import一个普通类 spring会将该类加载到spring容器中
2、@Import一个类,该类实现了ImportBeanDefinitionRegistrar接口,在重写的registerBeanDefinitions方法里面,能拿到BeanDefinitionRegistry bd的注册器,能手工往beanDefinitionMap中注册 beanDefinition
3、@Import一个类 该类实现了ImportSelector 重写selectImports方法该方法返回了String[]数组的对象,数组里面的类都会注入到spring容器当中
接下来挨个测试:
场景一 import普通类
- 自定义一个类 没有任何注解
public class MyClass {
public void test() {
System.out.println("test方法");
}
}
- 写一个importConfig类 import这个myClass类
@Import(MyClass.class)
public class ImportConfig {
}
- 通过AnnotationConfigApplicationContext 初始化spring容器 调用test方法 看输出, MyClass类被加载进了 spring容器当中
场景二、 实现ImportBeanDefinitionRegistrar
- 创建一个普通类MyClassRegistry
public class MyClassRegistry {
public void test() {
System.out.println("MyClassRegistry test方法");
}
}
- 创建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);
}
}
- import该类
@Import(MyImportRegistry.class)
public class ImportConfig {
}
- 执行main方法 查看输出
场景三、 实现ImportSelector
- 创建一个普通类MyClassImport
public class MyClassImport {
public void test() {
System.out.println("MyClassImport test方法");
}
}
- 创建MyImportSelector实现ImportSelector接口 注册我们定义的普通类MyClassImport
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] {MyClassImport.class.getName()};
}
}
- import该类
@Import(MyImportSelector.class)
public class ImportConfig {
}
- 执行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去初始化
版权归原作者 中年危机的老男人 所有, 如有侵权,请联系我们删除。