ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-02-08 09:29:55  阅读:118  来源: 互联网

标签:beanFactory Spring 扫描 BeanFactoryPostProcessor 源码 BeanDefinitionRegistryPostProc


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方法,于是笔者在对应的方法上打了一个断点。具体的如下:

在这里插入图片描述

我们最终发现调用的是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注解,这个时候就会执行两次
  • 具体的执行的流程如下图:
    在这里插入图片描述

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

在这里插入图片描述

我们可以看到这个类实现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

运行结果如下:

在这里插入图片描述

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

在这里插入图片描述

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

//这儿会取出所有的目前容器中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的方法。

标签:beanFactory,Spring,扫描,BeanFactoryPostProcessor,源码,BeanDefinitionRegistryPostProc
来源: https://blog.csdn.net/qq_33762302/article/details/113747204

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有