@Import注解详解
@Import注解详解
1.原文链接:https://blog.csdn.net/weixin_45453628/article/details/124234317
2. AnnotationConfigApplicationContext容器创建过程
https://www.cnblogs.com/ashleyboy/p/9662119.html
____________________________________________________________________________________________________________________________________________________________
@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去初始化。