Spring@Import注解的三种用法

服务接口
public interface IUserService {
    void sayHello();
}

服务实现

public class UserServiceImpl implements IUserService {
    @Override
    public void sayHello() {
        System.out.println("xxx");
    }
}

1.直接引入

@Import({UserServiceImpl.class})

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

2.引入ImportSelector的实现

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{UserServiceImpl.class.getName()};
    }
}

引入selector
@Import(MyImportSelector.class)
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

3.引入ImportBeanDefinitionRegistrar的实现

@Import(MyImportBeanDefinitionRegistrar.class)
@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

注册引入类的beanDefinition
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("userService", new RootBeanDefinition(UserServiceImpl.class));
    }
}

4.Import源码解析

以springBoot的启动容器 AnnotationConfigApplicationContext为例,容器创建的时候,会创建bean定义阅读器 AnnotatedBeanDefinitionReader,会往 beanFactorybeanDefinitionMap中注册 ConfigurationClassPostProcessor的beanDefinition【Spring IOC加载过程】。他是 BeanDefinitionRegistryPostProcessor的实现类,所以他在容器调用 invokeBeanFactoryPostProcessors方法的时候会被提前实例化出来,并调用。
入口
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
   int registryId = System.identityHashCode(registry);
   if (this.registriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
   }
   if (this.factoriesPostProcessed.contains(registryId)) {
      throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + registry);
   }
   this.registriesPostProcessed.add(registryId);


   processConfigBeanDefinitions(registry);
}

解析配置类上所有import导入的类getImports(sourceClass),找到候选类

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

   // 使用set跳过循环import 
   if (visited.add(sourceClass)) {
      for (SourceClass annotation : sourceClass.getAnnotations()) {
         String annName = annotation.getMetadata().getClassName();
         if (!annName.equals(Import.class.getName())) {
            // 递归解析非import注解,处理深层次的import
            collectImports(annotation, imports, visited);
         }
      }
      // 解析import注解的value属性  
      imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
   }
}

解析所有import直接引入的类

private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
      Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter,
      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) {
            // 如果引入的类是ImportSelector.class的实现类
            if (candidate.isAssignable(ImportSelector.class)) {
               // Candidate class is an ImportSelector -> delegate to it to determine imports
              // 根据类名加载class 
               Class<?> candidateClass = candidate.loadClass();
               // 实例化selector 
               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 {
                  // 调用自定义的selectImports方法,传入了@Import注解所在类的元数据,拿到导入的bean的类名
                  String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                  Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                  // 递归调用,如果引入的类也是importSelector或者ImportBeanDefinitionRegistrar也要解析
                  processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
               }
            }
            // 如果引入的类是ImportBeanDefinitionRegistrar.class的实现类
            else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
               // Candidate class is an ImportBeanDefinitionRegistrar ->
               // delegate to it to register additional bean definitions
               // 加载实现类class
               Class<?> candidateClass = candidate.loadClass();
               // 实例化实现类
               ImportBeanDefinitionRegistrar registrar =
                     ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                           this.environment, this.resourceLoader, this.registry);
                // 放进map里面存放起来importBeanDefinitionRegistrars等待调用
               configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
            }
            else {
               // 直接引入的类 存入importStack 
               // 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();
      }
   }
}

4.1如果引入的类是ImportBeanDefinitionRegistrar.class的实现类

把它加载并实例化出来,然后把它暂存到importBeanDefinitionRegistrars里面,等待后续的解析

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());
}

4.2如果引入的类是ImportSelector.class的实现类

加载并实例化

else {
   // 调用实现类的selectImports方法,拿到需要引入的类名 
   String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
   Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
   // 递归处理引入的类,最终转化为引入普通的类,从4.3出口出去 
   processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
}

4.3如果引入的类是其他的类

绑定引入的类和当前配置类,创建ConfigurationClass,等待后续解析

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);
}

候选类(引入的类)作为配置类来进行处理,等待后面的解析。candidate.asConfigClass(configClass),

在ConfigurationClass中会把当前类和引入类通过importedBy进行绑定,表示这是一个被引入的类。
后续在加载beanDefiniton的时候,通过configClass.isImported来判断,如果是被引入的类,那么就注册到beanDefinitionMap中
public ConfigurationClass(MetadataReader metadataReader, @Nullable ConfigurationClass importedBy) {
   this.metadata = metadataReader.getAnnotationMetadata();
   this.resource = metadataReader.getResource();
   this.importedBy.add(importedBy);
}

4.4从配置类加载beanDefinition

把bean定义写入到beanDefinitionMap中

this.reader.loadBeanDefinitions(configClasses);
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);
   }
   // 处理@Bean工厂方法引入 
   for (BeanMethod beanMethod : configClass.getBeanMethods()) {
      loadBeanDefinitionsForBeanMethod(beanMethod);
   }

   // 处理引入其他的配置文件 
   loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
   //  解析前面的importBeanDefinitionRegistrars,注册需要引入的beanDefinition
   loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
}

4.4.1普通引入类注册

private void registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass) {
   AnnotationMetadata metadata = configClass.getMetadata();
   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.isDebugEnabled()) {
      logger.debug("Registered bean definition for imported class '" + configBeanName + "'");
   }
}

4.4.2 ImportBeanDefinitionRegistrar 注册bean

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   for (Map.Entry<ImportBeanDefinitionRegistrar, AnnotationMetadata> entry : registrars.entrySet()) {
      entry.getKey().registerBeanDefinitions(entry.getValue(), this.registry);
   }
}

 

 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值