Spring源码分析系列(3)之@Import注解的底层原理?

1.@Import介绍

@Import就是用来向容器中导入bean的,可以导入标注了@ Configuration的类, 实现了ImportSelector接口、ImportBeanDefinitionRegistrar接口的类 ,也可以用于一个普通类的导入。被@Import的类是被加载到了Spring容器当中,因此无论是类本身还是类里面用@Bean注解定义的bean都可以被放入IOC容器中进行管理。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {
   /**
     * {@link Configuration @Configuration}, {@link ImportSelector},
     * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
   */
    Class<?>[] value();
}
  • @Target表明了它能作用的范围,可以作用于类、接口、枚举类

  • 属性仅有一个value,表示的是一个类对象数组。例如value = {xx.class,yy.class},表示要将xx和yy交给Spring容器管理。

2.导入的类大体可以分成三大类

实现了ImportSelector接口的类

 1 public interface ImportSelector {
 2 
 3     // 返回一个包含了类全限定名的数组,这些类会注入到Spring容器当中
 4     String[] selectImports(AnnotationMetadata importingClassMetadata);
 5 
 6     // 返回一个包含了类全限定名的数组,这些类会注入到Spring容器当中
 7     @Nullable
 8     default Predicate<String> getExclusionFilter() {
 9         return null;
10     }
11 
12 }

实现了ImportBeanDefinitionRegistrar接口的类

 1 public interface ImportBeanDefinitionRegistrar {
 2 
 3     // 注册Bean定义
 4     default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
 5             BeanNameGenerator importBeanNameGenerator) {
 6 
 7         registerBeanDefinitions(importingClassMetadata, registry);
 8     }
 9 
10     // 注册Bean定义
11     default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
12     }
13 
14 } 
 1 public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
 2 
 3     @Override
 4     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 5         BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
 6         AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
 7         registry.registerBeanDefinition("person", beanDefinition);
 8     }
 9 
10     //或者 使用如下的方法也可以,自动生成beanName
11     @Override
12     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) {
13         BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
14         AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
15         String beanName = importBeanNameGenerator.generateBeanName(beanDefinition, registry);
16         registry.registerBeanDefinition(beanName, beanDefinition);
17     }
18 }

3.配置类

4.普通类

3.源码分析:

private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
    //这个方法内部相当相当复杂,importCandidates是Import的内容,调用这个方法的时候,已经说过可能有三种情况
	//这里再说下,1.Import普通类,2.Import ImportSelector,3.Import ImportBeanDefinitionRegistrar
	//如果不是的话,调用selectImports方法,获得全限定类名数组,在转换成类的数组,然后再调用processImports,又特么的是一个递归调用...(这里就是spring在处理从selectImports方法中返回的全类名了,准备将它们作为配置类进行处理,也就是说如果string[]中返回的是普通类,又会调用processConfigurationClass,在调用它的过程中,就将其注册到工厂中了)
    if (!importCandidates.isEmpty()) {
        if (checkForCircularImports && this.isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new ConfigurationClassParser.CircularImportProblem(configClass, this.importStack));
        } else {
            this.importStack.push(configClass);

            try {
                Iterator var6 = importCandidates.iterator();

                while(var6.hasNext()) {
                    ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var6.next();
                    Class candidateClass;
          //如果Import ImportSelector就跑到了第一个if中来
                    if (candidate.isAssignable(ImportSelector.class)) {
                        candidateClass = candidate.loadClass();
           //  将导入的类进行实例化,实例化之后还会调用invokeAwareMethods方法,判断它是否实现了XxxAware接口,如果实现了,给其设置相应的组件
                        ImportSelector selector = (ImportSelector)ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
                        Predicate<String> selectorFilter = selector.getExclusionFilter();
                        if (selectorFilter != null) {
                            exclusionFilter = exclusionFilter.or(selectorFilter);
                        }
			// 判断selector是不是延迟导入类型的Selector,DeferredImportSelector扩展了ImportSelector,实现了此接口,不会在此处直接调用selector的selectImports()方法,而是会将其交给deferredImportSelectorHandler处理器后续处理,我们可以看一下这个处理器中做了什么?
								// 见下面↓↓↓
                        if (selector instanceof DeferredImportSelector) {
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector);
                        } else {
            // 如果不是DeferredImportSelector类型的,就直接调用它的selectImports方法,获取要注册的类的全类名数组
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
             //将获取到的想要注册到容器中的类名全部都解析成SourceClass对象(包含Class对象和注解元数据信息),放入集合中返回
                            Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
             // 再调用processImports()递归处理,也就是将他们当作Import({xxx.class})导入的xxx.class类来处理
                            this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                        }
                    } else if 
            	//如果Import ImportBeanDefinitionRegistrar就跑到了第二个if
           (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        candidateClass = candidate.loadClass();
                 // 实例化registrar注册器对象,在实例化后还是会调用Aware接口方法
                        ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
            // 会把数据放到ConfigurationClass中的Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars中去,注意此处还没有调用registrar的registerBeanDefinitions方法  
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    } else {
             //如果是普通类,会进到else,或者说只是没有实现ImportSelector和ImportBeanDefinitionRegistrar接口的类,因为我们通过调用selectImports()方法,获得的String[]中的类以及因为实现了DeferredImportSelector接口延迟调用了selectImports()方法获得的自动配置类(228个)-->springboot,如果没有实现上述两个接口,也会来到这里调用processConfigurationClass方法,将其当作配置类处理。
	//这个方法是不是很熟悉,没错,processImports这个方法就是在processConfigurationClass方法中被调用的
	//processImports又主动调用processConfigurationClass方法,是一个递归调用,因为Import的普通类,也有可能被加了@ImportResource、@ComponentScan注解 或者其他注解,所以普通类需要再次被解析         
 //将进入到else中的类名以及其注解元信息放入ImportStack的MultiValueMap<String, AnnotationMetadata> imports属性map中                    
                        this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                    }
                }
            } catch (BeanDefinitionStoreException var17) {
                throw var17;
            } catch (Throwable var18) {
                throw new BeanDefinitionStoreException("Failed to process import candidates for configuration class [" + configClass.getMetadata().getClassName() + "]", var18);
            } finally {
                this.importStack.pop();
            }
        }

    }
}


public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
    // 将实例化好的selector以及当前解析的配置类信息封装成了DeferredImportSelectorHolder
            ConfigurationClassParser.DeferredImportSelectorHolder holder = new ConfigurationClassParser.DeferredImportSelectorHolder(configClass, importSelector);
    // deferredImportSelectors 默认不为null,在创建ConfigurationClassParser解析器对象时,就初始化new了DeferredImportSelectorGroupingHandler对象,而在DeferredImportSelectorGroupingHandler的空参构造器中,就给该属性deferredImportSelectors创建了对象,它是ConfigurationClassParser.DeferredImportSelectorHolder类型的ArrayList
            if (this.deferredImportSelectors == null) {
                ConfigurationClassParser.DeferredImportSelectorGroupingHandler handler = ConfigurationClassParser.this.new DeferredImportSelectorGroupingHandler();
                handler.register(holder);
                handler.processGroupImports();
            } else {
        // 将当前的selector的持有者保存到list集合中,后续进行处理,这就体现了延迟(Deferred)
                this.deferredImportSelectors.add(holder);
            }

        }

如有问题欢迎指正.....

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值