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

 



 

posted @ 2021-04-20 16:35  0o飞行天下o0  阅读(225)  评论(0编辑  收藏  举报