• Spring源码@Import详解


    1、需要有一定基础才能看懂,忘谅解

    定位到核心方法

     2、找到具体调用的方法

    // Invoke factory processors registered as beans in the context.
                    invokeBeanFactoryPostProcessors(beanFactory);

    3、第一行就是

    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    4、第一次进来的话,只有一个proccessor

    String[] postProcessorNames =
                        beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

    返回值是ConfigrationClassPostProccessor类

    5、然后调用

    invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

    6、再调用for循环中

    postProcessor.postProcessBeanDefinitionRegistry(registry);

    7、进入返回值那个类中调用

    processConfigBeanDefinitions(registry);

    8、拿到基础类的beandefination 是个集合,调用  

    parser.parse(candidates);

    9、调用第一个

    try {
                    if (bd instanceof AnnotatedBeanDefinition) {
                        parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                    }

    10、最终掉到

    do {
                sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
            }

    11、终于到了关键地方

    // Process any @Import annotations
            processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    12、递归调用

    getImports(sourceClass)

    这个方法就是收集import进来的类

    private void collectImports(SourceClass sourceClass, Set<SourceClass> imports, Set<SourceClass> visited)
                throws IOException {
    
            if (visited.add(sourceClass)) {
                for (SourceClass annotation : sourceClass.getAnnotations()) {
                    String annName = annotation.getMetadata().getClassName();
                    if (!annName.equals(Import.class.getName())) {
                        collectImports(annotation, imports, visited);
                    }
                }
                imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
            }
        }

    在内部又调用了外部方法,是个递归,需要注意

    String annName = annotation.getMetadata().getClassName();获取到的不是当前的类名,而是souceClass对应的注解名称,最开始sourceClass是个普通的类,但是经过一次递归后,sourceClass就变成了
    注解本身,也就是接口本身,所以第二次调用就是从注解本身获取它上面的注解名称,然后再看上面还有没有注解,直到最底层一级,然后调用最底层一级的
    sourceClass.getAnnotationAttributes(Import.class.getName(), "value");因为递归一直走,会把所有最底层有import注解的类收集到imports中。完成@Import注解中类的收集。
    进入中processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    很明显不同类型的Import会有不同的方法调用,不再细说

    Class<?> candidateClass = candidate.loadClass();
                            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 {
                                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                                Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                                processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                            }


  • 相关阅读:
    编码器-解码器模型--本人实现
    Encoder-Decoder 架构实现
    一些数据集
    论文跟踪
    Densenet 实现
    多种卷积网络实现
    vs2019 指定项目输出目录和指定中间目录
    poi java读取excel文件
    eclipse配置tomcat添加外部项目
    eclipse配置tomcat
  • 原文地址:https://www.cnblogs.com/zxg-blog/p/14681690.html
Copyright © 2020-2023  润新知