Spring源码系列(五)Spring扫描机制(二)

1.写在前面

上一篇博客中讲到的Spring的扫描机制,但是讲的是Spring提供给外部的api,而且创建的在AnnotationConfigApplicationContext的构造函数中创建的scanner属性,创建的ClassPathBeanDefinitionScanner对象,Spring自己根本没有使用,这个对象是暴露给外部的人使用的。今天我们就真正来讲下Spring是如何扫描的?这里要注意的是Spring扫描也是用这个类的,但是Spring没有用这个scanner属性,而是自己重新创建了一个ClassPathBeanDefinitionScanner对象的,所以机制也是一样的,主要的是这两个过滤函数。同时会涉及到一些BeanFactoryPostProcessor的知识,这儿笔者建议读者:最好将笔者的整个Spring的源码系列全都看了,不然可能会看不懂。Spring的体系过于庞大,一篇两篇博客,讲不清楚,笔者写的每一篇博客都是有关联的。

2.BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor

凡是了解过Spring的人,都是知道实现这个接口的类,都会对BeanDefinition进行修改,然后再放到BeanFactoryBeanDefinitionMap的集合中去。但是Spring在初始化的时候,只会添加5个默认的BeanDefinition,分别是ConfigurationClassPostProcessor(BeanFactoryPostProcessor)、AutowiredAnnotationBeanPostProcessor(BeanPostProcessor)、CommonAnnotationBeanPostProcessor(BeanPostProcessor)、EventListenerMethodProcessor(BeanFactoryPostProcessor)、DefaultEventListenerFactory,注意:如果这儿添加了JPA的支持的话,会再添加一个PersistenceAnnotationBeanPostProcessor,然后会调用AnnotationConfigApplicationContextregister方法,将我们的配置类也会注册进来。那么就会有6个。那么可能读者就有疑问了。那么我们自己写Bean还没有转换成BeanDefinition添加到BeanDefinitionMap中去呀,那么又是怎么添加进去的呢?又是谁添加的呢?我们现在已经知道了默认的BeanDefinitionMap中已经有了6个BeanDefinition对象。那么肯定是其中那个对象呢?笔者作为一个新手,第一次阅读Spring的源码,那么我们该怎么知道是那个对象呢?唯一的办法就是打断点,然后看对应的调用栈,那么该怎么打断点呢?让我们想到了上篇博客中写道的。扫描Class将其转成BeanDefinition并添加到BeanDefinitionMap中去,是调用的是doscan方法,于是笔者在对应的方法上打了一个断点。具体的如下:

Spring源码系列(五)Spring扫描机制(二)

我们最终发现调用的是ConfigurationClassPostProcessor类中的方法。

2.1执行顺序

既然知道了是调用这个类中方法,那么Spring又是怎么调用它的?又是调用它中的那个方法呢?这就是本节要回答的问题。

先回答第一个问题,Spring怎么调用到它的?在那个方法中调用的。我们可以看上面的调用栈。我们发现最终的调用链如下:

AnnotationConfigApplicationContext#init()
--->AbstractApplicationContext#refresh()
--->AbstractApplicationContext#invokeBeanFactoryPostProcessors()
--->PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
  • 1
  • 2
  • 3
  • 4

后面的调用链,我没有继续写了,是因为这个方法比较重要,笔者这里要讲一下这个方法。具体的代码如下:

public static void invokeBeanFactoryPostProcessors(
    ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    
    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    Set<String> processedBeans = new HashSet<>();

    //DefaultListableBeanFactory这个类实现了BeanDefinitionRegistry,这个判断是会进
    if (beanFactory instanceof BeanDefinitionRegistry) {
        //用一个变量存起来
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        //创建一个BeanFactoryPostProcessor的集合
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        //创建一个BeanDefinitionRegistryPostProcessor的集合
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
        
        //这个时候beanFactoryPostProcessors的集合为空
        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                    (BeanDefinitionRegistryPostProcessor) postProcessor;
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                registryProcessors.add(registryProcessor);
            }
            else {
                regularPostProcessors.add(postProcessor);
            }
        }

        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        //创建一个BeanDefinitionRegistryPostProcessor的集合,表示当前的要执行的BeanDefinitionRegistryPostProcessor
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        //从BeanFactory的BeanDefinitionMap中取出实现BeanDefinitionRegistryPostProcessor的类型的键名,
        //这个时候只能取出一个,就是ConfigurationClassPostProcessor
        String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //判断是否实现了PriorityOrdered接口,这个时候取出来的是ConfigurationClassPostProcessor
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                //添加到currentRegistryProcessors集合中去
                //getBean的含义:如果容器中这个对象已经创建好了,直接取,如果容器中这个对象没有创建好,那我们就new
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                //存入对应的名字
                processedBeans.add(ppName);
            }
        }
        //对BeanDefinition进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //添加到registryProcessors
        registryProcessors.addAll(currentRegistryProcessors);
        //执行BeanDefinitionRegistryPostProcessor的接口的实现类ConfigurationPostProcessor中的postProcessBeanDefinitionRegistry方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清空当前要执行的集合
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        //再次查找实现BeanDefinitionRegistryPostProcessor接口的类名
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            //查询出来的如果上次没有执行过同事也是实现Ordered接口的实现类,会进入这个判断
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                //同时添加到当前要执行BeanDefinitionRegistryPostProcessor的集合
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                //同时添加到对应的集合,可以简单说就是执行过的
                processedBeans.add(ppName);
            }
        }
        //进行排序
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        //添加到总的
        registryProcessors.addAll(currentRegistryProcessors);
        //执行接口中实现类的指定的方法
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
        //清除当前的集合
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        //再次查找
        boolean reiterate = true;
        //这个死循环就能保证所有实现BeanDefinitionRegistryPostProcessor的接口类都会执行
        while (reiterate) {
            reiterate = false;
            //查找实现BeanDefinitionRegistryPostProcessor接口的实现类
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        //执行所有所有实现BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,这儿可能会有人说这儿不是执行了两次,
        //然而并不是,因为里面进行了对应的判断,判断对应的hash的值
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        //执行所有所有实现BeanFactoryPostProcessor的postProcessBeanFactory方法,这个默认是为空的,
        //只有通过调用addBeanFactoryPostProcessor()的BeanFactoryPostProcessor才会在这执行。
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    //获取对应实现BeanFactoryPostProcessor接口的类
    String[] postProcessorNames =
        beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    // 实现PriorityOrdered和BeanFactoryPostProcessor接口的类,最先执行
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    // 实现Ordered和BeanFactoryPostProcessor接口的类,次之执行
    List<String> orderedPostProcessorNames = new ArrayList<>();
    // 实现BeanFactoryPostProcessor接口的类,最后执行
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        //已经执行过的
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    // 对实现PriorityOrdered和BeanFactoryPostProcessor接口的类进行排序
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    // 执行接口的实现方法
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 对实现Ordered和BeanFactoryPostProcessor接口的类进行排序
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 执行接口对应的方法
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    // 只实现了BeanFactoryPostProcessor的接口的类存入下面的集合。
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    // 执行接口对应的方法
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174

虽然上面的代码写了注释,但是自己还是总结一下吧!不然对读者来说看的是云里雾里。

总结,执行顺序如下:

  • 最先执行的是通过调用addBeanFactoryPostProcessor()方法添加的的BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanDefinitionRegistry()方法。如果有多个,是按照添加的顺序来执行的。
  • 然后执行同时实现了PriorityOrderedBeanDefinitionRegistryPostProcessor接口中的实现类中的postProcessBeanDefinitionRegistry()方法。如果有多个,按照对应的排序规则来执行的。
  • 再执行同时实现OrderedBeanDefinitionRegistryPostProcessor接口中的实现类中的postProcessBeanDefinitionRegistry()方法。如果有多个,按照对应的排序规则来执行的。
  • 再执行实现了BeanDefinitionRegistryPostProcessor接口中的实现类中的postProcessBeanDefinitionRegistry()方法。如果有多个,就按照添加的顺序来执行。
  • 再执行BeanDefinitionRegistryPostProcessor接口中的实现类中的postProcessBeanFactory()方法。如果有多个,就按照添加的顺序来执行。
  • 再执行通过调用addBeanFactoryPostProcessor()方法添加的的BeanFactoryPostProcessor接口的实现类中的postProcessBeanFactory()方法。如果有多个,是按照添加的顺序来执行的。
  • 再执行同时实现了PriorityOrderedBeanFactoryPostProcessor接口的实现类中的postProcessBeanFactory()方法。如果有多个,按照对应的排序规则来执行的。
  • 再执行同时实现了OrderedBeanFactoryPostProcessor接口的实现类中的postProcessBeanFactory()方法。如果有多个,按照对应的排序规则来执行的。
  • 最后执行实现了BeanFactoryPostProcessor接口的实现类的postProcessBeanFactory()方法。如果有多个,按照添加的顺序来执行。
  • 注意:Spring并没有完全保证每一个类只执行一次。如果我们通过addBeanFactoryPostProcessor()方法添加的的BeanFactoryPostProcessor接口的实现类,然后给这个类添加@Component注解,这个时候就会执行两次
  • 具体的执行的流程如下图:
    Spring源码系列(五)Spring扫描机制(二)

这个时候读者可能有疑问,BeanDefinitionRegistryPostProcessor又是什么接口?我们只知道BeanFactoryPostProcessor接口。这儿笔者告诉你这个BeanDefinitionRegistryPostProcessor就是BeanFactoryPostProcessor的子接口。这个时候我们已经讲完了对应invokeBeanFactoryPostProcessors()方法,但是我们还没有讲到对应ConfigurationClassPostProcessor类。我们来看下对应继承的类图,具体如下:

Spring源码系列(五)Spring扫描机制(二)

我们可以看到这个类实现BeanDefinitionRegistryPostProcessorBeanFactoryPostProcessorOrderedPriorityOrdered接口。那么由上面的执行顺序和AnnotationConfigApplicationContext的初始化的过程,我们可以得知最先执行的是这个类中postProcessBeanDefinitionRegistry方法。

2.2ConfigurationClassPostProcessor

由上面的调用链可知,我们发现调用的是invokeBeanDefinitionRegistryPostProcessors的方法,具体的代码如下:

private static void invokeBeanDefinitionRegistryPostProcessors(
    Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {

    //循环调用所有的BeanDefinitionRegistryPostProcessor接口的实现类的postProcessBeanDefinitionRegistry的方法
    for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {
        postProcessor.postProcessBeanDefinitionRegistry(registry);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

上面的代码就是循环调用所有的BeanDefinitionRegistryPostProcessor接口的实现类的postProcessBeanDefinitionRegistry的方法,我们直接查看ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry(),具体的代码如下:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    //获取对应的hash的值
    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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

然后会调用对应的 processConfigBeanDefinitions()的方法,具体的代码如下:

//这个方法过于复杂,由于博客的篇幅有限,不会全都讲,只会讲重点的部分。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    //用来存BeanDefinition的包装类BeanDefinitionHolder
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    //这儿会取出所有的目前容器中BeanDefinition,现在是6个
    String[] candidateNames = registry.getBeanDefinitionNames();

    //遍历获取对应的配置类
    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // Return immediately if no @Configuration classes were found
    // 判断是否有对应的配置类
    if (configCandidates.isEmpty()) {
        return;
    }

    //下面的代码后面的博客会讲
    // Sort by previously determined @Order value, if applicable
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // Detect any custom bean name generation strategy supplied through the enclosing application context
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    //将对应的配置类放到对应set集合中去,配置类可能有多个
    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        //解析对应的配置类
        parser.parse(candidates);
        parser.validate();

        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                registry, this.sourceExtractor, this.resourceLoader, this.environment,
                this.importBeanNameGenerator, parser.getImportRegistry());
        }
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);

        candidates.clear();
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                        !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());
    
    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
        // Clear cache in externally provided MetadataReaderFactory; this is a no-op
        // for a shared cache since it'll be cleared by the ApplicationContext.
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110

3.什么样的类可以解析成配置类?

什么样的类可以作为我们的配置类呢?一定要加@Configuration的类吗?下面就由笔者为你一一解答这个问题。由于上面的代码太长,我们直接取出我们核心要将的部分。具体的代码如下:

//这儿会取出所有的目前容器中BeanDefinition,现在是6个
String[] candidateNames = registry.getBeanDefinitionNames();

//遍历获取对应的配置类
for (String beanName : candidateNames) {
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    //判断这个org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass是不是为空
    if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
        if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
    }
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
}

// Return immediately if no @Configuration classes were found
// 判断是否有对应的配置类
if (configCandidates.isEmpty()) {
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

上面的candidateNames取出来的值现在应该是6个,也就是目前BeanFactory中的所有的BeanDefinition,这儿其中有5个是Spring提供的,并不是我们自己的,所以Spring要找出我们的配置类。

走来Spring会先判断这个BeanDefinition中的attribute的属性的键为org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass的是不是不等于null,这个属性在解析讲BeanDefinition的时候已经讲过了。这儿对应的五个为空的。我们这儿可以搞一个破坏,哈哈!就是在Spring容器初始化之前,我们将AppConfigBeanDefinition的信息给改了,让这个值不为null,那么就不会有对应的配置类,就会报错!我们可以试下效果,具体的代码如下:

package com.ys.annotationConfigApplicationContextTest;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration()
@ComponentScan("com.ys.annotationConfigApplicationContextTest")
public class AppConfig {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
package com.ys.annotationConfigApplicationContextTest;

import org.springframework.stereotype.Component;

@Component
public class A  {

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
package com.ys.annotationConfigApplicationContextTest;

import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(AppConfig.class);
        AnnotatedGenericBeanDefinition appConfig = (AnnotatedGenericBeanDefinition) 	context.getBeanFactory().getBeanDefinition("appConfig");
        //修改对应的属性的值。
        appConfig.setAttribute("org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass", true);
        context.refresh();
        context.getBean(A.class);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行结果如下:

Spring源码系列(五)Spring扫描机制(二)

如果我们将我们修改的属性的那个代码注释掉,这个就不会报错,具体的运行结果如下:

Spring源码系列(五)Spring扫描机制(二)

通过这个例子,上面的那个判断应该理解更透彻了吧。我们继续看原来的代码,具体的代码如下:

//这儿会取出所有的目前容器中BeanDefinition,现在是6个
String[] candidateNames = registry.getBeanDefinitionNames();

//遍历获取对应的配置类
for (String beanName : candidateNames) {
    BeanDefinition beanDef = registry.getBeanDefinition(beanName);
    //判断这个org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass是不是为空
    if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
        if (logger.isDebugEnabled()) {
            logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
        }
    }
    else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
        configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
    }
}

// Return immediately if no @Configuration classes were found
// 判断是否有对应的配置类
if (configCandidates.isEmpty()) {
    return;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

如果我们不搞破坏的话,第一个判断是不会进的,我们继续看第二个判断ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory),具体的代码如下:

public static boolean checkConfigurationClassCandidate(
    BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

    //获取对应的className
    String className = beanDef.getBeanClassName();
    //有可能是通过工厂方法注解进来的BeanDefinition,直接返回false
    if (className == null || beanDef.getFactoryMethodName() != null) {
        return false;
    }

    AnnotationMetadata metadata;
    //判断是不是AnnotatedBeanDefinition的BeanDefinition,还记得我第一篇博客中的内容,就知道这个接口有三个实现类。
    //分别是AnnotatedGenericBeanDefinition、ScannedGenericBeanDefinition、ConfigurationClassBeanDefinition
    if (beanDef instanceof AnnotatedBeanDefinition &&
        className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
        // Can reuse the pre-parsed metadata from the given BeanDefinition...
        // 获取对应的bean注解的元数据存起来
        metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
    }
    else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {//所有的BeanDefinition都会满足
        // Check already loaded Class if present...
        // since we possibly can't even load the class file for this Class.
        //取出对应的BeanClass
        Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
        //判断是不是下面的四种类型的一种。
        if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
            BeanPostProcessor.class.isAssignableFrom(beanClass) ||
            AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
            EventListenerFactory.class.isAssignableFrom(beanClass)) {
            return false;
        }
        metadata = AnnotationMetadata.introspect(beanClass);
    }
    else {
        try {
            MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
            metadata = metadataReader.getAnnotationMetadata();
        }
        catch (IOException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Could not find class file for introspecting configuration annotations: " +
                             className, ex);
            }
            return false;
        }
    }

    //取出这个Configuration这个注解的数据
    Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
    if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {//不为空,同时判断方法需不需要代理
        //给对应的属性org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass设置为full
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
    }
    else if (config != null || isConfigurationCandidate(metadata)) {//如果没有该注解,则调用isConfigurationCandidate(metadata)方法
        //给对应的属性org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass设置为lite
        beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
    }
    else {//都不成立直接返回false
        return false;
    }

    // It's a full or lite configuration candidate... Let's determine the order value, if any.
    // 判断是否有order注解,有直接取出来,然后将其设置到attribute中去
    Integer order = getOrder(metadata);
    if (order != null) {
        beanDef.setAttribute(ORDER_ATTRIBUTE, order);
    }

    return true;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

上面的判断,如果是实现AnnotatedBeanDefinitionBeanDefinition或者是AbstractBeanDefinition但不是BeanFactoryPostProcessorBeanPostProcessorAopInfrastructureBean、 EventListenerFactory,再或者是自己实现的BeanDefinition添加到BeanDefinitionMap中的BeanDefinition就不会返回false然后进行第二次筛选,如果是添加了Configuration注解的类是不会返回false的,还有种就是isConfigurationCandidate(metadata)方法的返回值不为false的,也是不会返回false的,那么这个方法中是做了什么?具体的代码如下:

public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
    // Do not consider an interface or an annotation...
    //如果是接口直接返回false
    if (metadata.isInterface()) {
        return false;
    }

    // Any of the typical annotations found?
    //Component ComponentScan Import ImportResource 四个注解中一个会返回true
    for (String indicator : candidateIndicators) {
        if (metadata.isAnnotated(indicator)) {
            return true;
        }
    }

    // Finally, let's look for @Bean methods...
    try {
        //最后一种有方法添加了这个@Bean注解
        return metadata.hasAnnotatedMethods(Bean.class.getName());
    }
    catch (Throwable ex) {
        if (logger.isDebugEnabled()) {
            logger.debug("Failed to introspect @Bean methods on class [" + metadata.getClassName() + "]: " + ex);
        }
        return false;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

上面的方法,我们可以得知,如果是接口会直接返回false,如果是Component ComponentScan Import ImportResource 四个注解中一个会返回true,如果在方法上添加了@Bean注解也是会返回true。所以最终的解答这个问题,什么样的类可以解析成配置类?

当这个BeanDefinitionAnnotatedBeanDefinition或者是AbstractBeanDefinition但不是BeanFactoryPostProcessorBeanPostProcessorAopInfrastructureBean、 EventListenerFactory,再或者是自己实现的BeanDefinition,同时这个BeanDefinition如果加了Configuration的注解,并且这个注解的proxyBeanMethods的值为true,就会将org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass设置为full或者没有加Configuration的注解,但是这个BeanDefinition不是接口,或者是Component ComponentScan Import ImportResource 四个注解中一个再或者是有方法添加了Bean注解这样的BeanDefinition就会将org.springframework.context.annotation.ConfigurationClassPostProcessor.configurationClass设置为lite所以满足上面的两种情况的任何一种都可以被解析成配置类。至此这节介绍完了。接下来我们看怎么调用doscan的方法的。

4.Spring如何调用到doscan的方法

通过断点调试,我们发现调用的 parser.parse(candidates);方法,将刚才找到的配置进行进行解析,具体的代码如下:

public void parse(Set<BeanDefinitionHolder> configCandidates) {
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
            }
            else {
                parse(bd.getBeanClassName(), holder.getBeanName());
            }
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
        }
    }
    this.deferredImportSelectorHandler.process();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

这儿三个判断真好对应前面的三种情况的BeanDefinition的解析。这儿我们只需要看第一个if中的方法parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());同时将注解的元数据和对应的BeanName传进去了。具体的代码如下:

protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }

    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    if (existingClass != null) {
        if (configClass.isImported()) {
            if (existingClass.isImported()) {
                existingClass.mergeImportedBy(configClass);
            }
            // Otherwise ignore new imported config class; existing non-imported class overrides it.
            return;
        }
        else {
            // Explicit bean definition found, probably replacing an import.
            // Let's remove the old one and go with the new one.
            this.configurationClasses.remove(configClass);
            this.knownSuperclasses.values().removeIf(configClass::equals);
        }
    }

    // Recursively process the configuration class and its superclass hierarchy.
    SourceClass sourceClass = asSourceClass(configClass, filter);
    do {
        //扫描的方法在这个方法中
        sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
    }
    while (sourceClass != null);
    
    this.configurationClasses.put(configClass, configClass);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

由于篇幅的原因,我们只介绍重要的方法 doProcessConfigurationClass(configClass, sourceClass, filter);,具体的代码如下:

@Nullable
protected final SourceClass doProcessConfigurationClass(
    ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
    throws IOException {

    if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
        // Recursively process any member (nested) classes first
        processMemberClasses(configClass, sourceClass, filter);
    }

    // Process any @PropertySource annotations
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), PropertySources.class,
        org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        }
        else {
            logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
        }
    }

    // Process any @ComponentScan annotations
    Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() &&
        !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // The config class is annotated with @ComponentScan -> perform the scan immediately
            Set<BeanDefinitionHolder> scannedBeanDefinitions =
                this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
            // Check the set of scanned definitions for any further config classes and parse recursively if needed
            for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                if (bdCand == null) {
                    bdCand = holder.getBeanDefinition();
                }
                if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                    parse(bdCand.getBeanClassName(), holder.getBeanName());
                }
            }
        }
    }

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

    // Process any @ImportResource annotations
    AnnotationAttributes importResource =
        AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

    // Process individual @Bean methods
    Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // Process default methods on interfaces
    processInterfaces(configClass, sourceClass);

    // Process superclass, if any
    if (sourceClass.getMetadata().hasSuperClass()) {
        String superclass = sourceClass.getMetadata().getSuperClassName();
        if (superclass != null && !superclass.startsWith("java") &&
            !this.knownSuperclasses.containsKey(superclass)) {
            this.knownSuperclasses.put(superclass, configClass);
            // Superclass found, return its annotation metadata and recurse
            return sourceClass.getSuperClass();
        }
    }

    // No superclass -> processing is complete
    return null;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

看这上面的代码,真的是头皮发麻,所以这儿笔者抽出处理ComponentScan的部分的代码,具体的代码如下:

//取出ComponentScan注解中的数据
Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
    sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
//判断是不是为空
if (!componentScans.isEmpty() &&
    !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
    //这儿应该就只有一个,因为只加了一个ComponentScan注解
    for (AnnotationAttributes componentScan : componentScans) {
        // The config class is annotated with @ComponentScan -> perform the scan immediately
        //解析ComponentScan注解
        Set<BeanDefinitionHolder> scannedBeanDefinitions =
            this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
        // Check the set of scanned definitions for any further config classes and parse recursively if needed
        for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
            BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
            if (bdCand == null) {
                bdCand = holder.getBeanDefinition();
            }
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                parse(bdCand.getBeanClassName(), holder.getBeanName());
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

上面的方法this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());方法就是解析ComponentScan注解,具体的代码如下:

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
    //重新创建了一个ClassPathBeanDefinitionScanner,并且是否使用默认的配置,是由注解中指定的。这个如果没有设置的话,就使用的是默认
    //就会给includeFilters添加一个Component注解
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                                                                                componentScan.getBoolean("useDefaultFilters"), 
                                                                                this.environment, this.resourceLoader);

    //获取对应的名字的生成规则
    Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    //如果已经给定自己的生成规则就使用的自己的
    scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                                 BeanUtils.instantiateClass(generatorClass));

    //获取作用域代理模型并设置好
    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    }
    else {
        Class<? extends ScopeMetadataResolver> resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }

    // **/*.class,这个也可以指定扫描的后缀
    scanner.setResourcePattern(componentScan.getString("resourcePattern"));

    //包含在内的注解,自己定义
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }
    
    //不包含在内的注解,自己定义
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }

    //获取是否是懒加载的
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }

    //扫描的路径
    Set<String> basePackages = new LinkedHashSet<>();
    String[] basePackagesArray = componentScan.getStringArray("basePackages");
    for (String pkg : basePackagesArray) {
        String[] tokenized = StringUtils.tokenizeToStringArray(this.environment.resolvePlaceholders(pkg),
                                                               ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
        Collections.addAll(basePackages, tokenized);
    }
    for (Class<?> clazz : componentScan.getClassArray("basePackageClasses")) {
        basePackages.add(ClassUtils.getPackageName(clazz));
    }
    if (basePackages.isEmpty()) {
        basePackages.add(ClassUtils.getPackageName(declaringClass));
    }
	
    //将当前AppConfig排除在外,因为这个东西已经注解了BeanDefinition。所以要排除在外。
    scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
        @Override
        protected boolean matchClassName(String className) {
            return declaringClass.equals(className);
        }
    });
    //终于调用到我们的doscan的方法了
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

至此这儿定义了我们自动的ClassPathBeanDefinitionScanner,大部分的东西都是从注解中获取的。这儿会给ExcludeFilter属性中添加一个排除当前配置类的,因为配置类已经注册过了。然后就会调用到我们的doScan()方法了。至此终于讲完了。

5.写在最后

这篇博客主要讲BeanFactoryPostProcessorBeanDefinitionRegisterPostProcessor的执行顺序,同时讲了一下Spring中很重要的一个类ConfigurationClassPostProcessor类,最后和上一篇博客关联起来,讲了一下Spring是怎么调用的doscan的方法。

上一篇:Spring七大模块


下一篇:别再BeanFactory和FactoryBean傻傻分不清楚