2.3 spring5源码系列---内置的后置处理器PostProcess加载源码(三)

291 阅读7分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

7. 详细研究四次调用中的第一次调用.  通过分析跟踪@ComponentScan注解是如何解析的,

通过跟踪@ComponentScan注解是如何解析的, 分来理解BeanDefinitionScan, BeanDefinitionRegistry, BeanDefinitionReader是如何工作的. 

 

复制代码

public static void invokeBeanFactoryPostProcessors(
            ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

        /**
         * 首先,调用BeanDefinitionRegistryPostProcessors 的后置处理器
         * 定义已处理的后置处理器
         */
        // Invoke BeanDefinitionRegistryPostProcessors first, if any.
        Set<String> processedBeans = new HashSet<>();

        /**
         * 这里一共分为两大步:
         * 第一步: 调用所有实现了 BeanDefinitionRegistryPostProcessor 接口的bean定义. (BeanDefinitionRegistryPostProcessor带注册功能的后置处理器)
         * 第二步: 调用BeanFactoryPostProcessor Bean工厂的后置处理器
         */

        /**********************第一步: 调用所有实现了BeanDefinitionRegistryPostProcessor接口的bean定义  begin****************************/
        // 判断beanFactory是否实现了BeanDefinitionRegistry, 实现了该结构就有注册和获取Bean定义的能力
        if (beanFactory instanceof BeanDefinitionRegistry) {
            BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
            List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
            List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

            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
             */
            List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
            // 首先, 调用实现了PriorityOrdered的BeanDefinitionRegistryPostProcessors
            // 在所有创世纪的后置处理器中, 只有 internalConfigurationAnnotationProcessor 实现了 BeanDefinitionRegistryPostProcessors 和 PriorityOrdered
            // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
            String[] postProcessorNames =
                    beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                // 判断beanFactory是否实现了PriorityOrdered接口. 如果实现了,是最优先调用.
                // 在整个加载过程中,会调用四次BeanDefinitionRegistryPostProcessor, 而实现了PriorityOrdered的接口最先调用
                if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                    // 调用beanFactory.getBean实例化配置类的后置处理器(创世界的类ppName), 也就是初始化, 实例化, 赋值属性.
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class ) );
                    processedBeans.add(ppName);
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            /**
             * 第一次调用BeanDefinitionRegistryPostProcessors
             * 在这里典型的BeanDefinitionRegistryPostProcessors就是ConfigurationClassPostProcessor
             * 用于进行bean定义的加载 比如我们的包扫描 @import 等
             */ invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); // 处理完了,清空currentRegistryProcessors
            currentRegistryProcessors.clear();

复制代码

这里也有两大步

第一步: 初始化bean工厂的后置处理器

  通过调用beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class ) 初始化了bean工厂的后置处理器,

第二步: 解析配置

   调用invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);调用beanDefinitionRegistry的后置处理器. 筛选出符合条件的配置类.

 

如上图所示, 最后筛选出的配置类只有MainConfig配置类. 也就是说configCandidates配置候选集合中只有一个MainConfig

复制代码

      // 创建一个ConfigurationClassParser对象, 解析@Configuration class
        ConfigurationClassParser parser = new ConfigurationClassParser(
                this.metadataReaderFactory, this.problemReporter, this.environment,
                this.resourceLoader, this .componentScanBeanNameGenerator, registry); 

        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
             // 执行解析  parser.parse(candidates); 
            parser.validate();

复制代码

 

然后, 接下来创建了一个对象ConfigurationClassParser, 这是一个配置类解析器. 下面将使用这个解析器解析配置类.

重点是如何解析的, 代码已重点标注出来了.

 // 执行解析
parser.parse(candidates); 

我们这里是通过注解解析的, 所以直接看下面的代码

复制代码

public void parse(Set<BeanDefinitionHolder> configCandidates) {
        // 循环配置类
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                // 真正的解析bean定义:通过注解元数据解析
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName()); 
                }
......
}

复制代码

 

解析主要做了几件事呢?如下图:

 

 解析配置类, 看看配置类是否含有如上标记的注解, 如果有, 则调用响应的返回对其进行解析,处理.

下面来看看源码. 是如何处理这一块的.

复制代码

/**
     * 在这里会解析@Component  @PropertySources @ComponentScan @ImportResource
     * @param configClass
     * @param sourceClass
     * @param filter
     * @return
     * @throws IOException
     */
    @Nullable
    protected final SourceClass doProcessConfigurationClass(
            ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
            throws IOException {

         // 1. 处理@Component注解,判断元数据是否带有Component注解
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            processMemberClasses(configClass, sourceClass, filter);
        }

        // Process any @PropertySource annotations
         // 2. 处理@PropertySource 注解, 判断元数据是否带有@PropertySource注解
        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
        // 3. 处理@ComponentScan注解, 判断元数据是否带有@ComponentScan注解
        /**
         * 这里mainConfig配置类中有两个注解,一个是@Configuration ,一个是@ComponentScan. 在这里, 我们看一下@ComponentScan
         */
        //componentScans 拿到的就是ComponentScan注解里的属性
        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
                // 解析扫描出来的类, 将其解析为BeanDefinitionHolder对象, 并放入到scannedBeanDefinitions中
                // 这正的解析ComponentScans和ComponentScan中的配置
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // 循环处理包扫描出来的bean定义
                // 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());
                    }
                }
            }
        }

         // 4. 处理@Import注解 // Process any @Import annotations
        processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

         // 5. 处理@ImportResource注解 // 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);
            }
        }

         // 6. 处理@Bean注解 // 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;
    }

复制代码 下面我们重点看对@ComponentScan和@ComponentScans注解的解析, 为什么看他呢? 因为很多注解都标记了@Component注解. 

比如@Service注解,本身使用@Component

 

 再来看@Controller注解, 其实质也是一个@Component注解

 

 我们在自定义配置类的时候, 会使用@ComponentScan注解. 并传递一个包, 作为扫描包. 如MainConfig配置

 

 这就会扫描包下所有的配置类. 

它主要的逻辑如下:

 

 在拿到@ComponentScan注解以后, 会对其进行parse. 主要解析里面的注解. 并对每一个注解进行处理. 处理后将其添加到scanner属性中. 最后调用scanner.doScan(....)方法.

源码如下:

复制代码

// 解析配置
    public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
         // 定义了一个类路径扫描器ClassPathBeanDefinitionScanner // 这里的scanner用于读取配置类
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader); // 1. 判断是否有nameGenerator注解 // 为扫描器设置beanName的生成器对象, 并赋值给scanner, BeanNameGenerator的作用是为bean definitions生成Bean名字的接口
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

         // 2. 判断是否有scopedProxy注解
        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));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));

         // 3. 判断属性中是否有includeFilters属性, 有的话就添加到scanner中 // 设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器, 这里进行处理
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

         // 4. 判断属性总是否有excludeFilters属性, 有的话放到scnanner中 // 设置componentScan中排除的过滤器
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

         // 5. 判断是否有lazyInit属性 // 获取配置类中懒加载初始化的属性
        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set<String> basePackages = new LinkedHashSet<>();

         // 6. 判断是否有basePackages属性 // 获取basePackages属性, 也就是我们定义的包扫描路径
        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));
        }

        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            @Override
            protected boolean matchClassName(String className) {
                return declaringClass.equals(className);
            }
        });

         // 调用scanner.doScan()方法, 扫描basePackages包
        return scanner.doScan( StringUtils.toStringArray(basePackages));
    }

复制代码

 

调用doScan方法扫描配置类. 我们来看看主要做了哪些事情

 

 

 第一步: 找到所有候选的BeanDefinition.

  上面解析出了@ComponentScan注解传递过来的basePackages包. 扫描包中所有的类, 得到候选类. 

  扫描的时候做了几件事呢? 看最上图最右侧部分. 这扫描出来就是我们的目标类.

 第二步: 解析这些准目标类. 

第三步: 设置默认的beanDefinition属性

复制代码

/**
     * 设置默认的bean定义的信息
     * Apply the provided default values to this bean.
     * @param defaults the default settings to apply
     * @since 2.5
     */
    public void applyDefaults(BeanDefinitionDefaults defaults) {
        // 设置这个类是不是懒加载的
        Boolean lazyInit = defaults.getLazyInit();
        if (lazyInit != null) {
            setLazyInit(lazyInit);
        }
        // 设置默认的自动装配方式
        setAutowireMode(defaults.getAutowireMode());
        setDependencyCheck(defaults.getDependencyCheck());
        // 设置初始化方法的名称
        setInitMethodName(defaults.getInitMethodName());
        // 是否可以调用InitMethod方法
        setEnforceInitMethod(false);
        setDestroyMethodName(defaults.getDestroyMethodName());
        // 是否可以调用DestroyMethod方法
        setEnforceDestroyMethod(false);
    }

复制代码

 

 第四步: 将解析出来的bean定义注册到ioc容器中

 这里就调用了BeanDefinitionReaderUtils.registerBeanDefinition注册bean定义. 之前注册过配置类, 这里和其是一样的. 所以不再赘述了

 

这里有两个细节:

  1. excludeFilter中排除了自己

复制代码

public Set<BeanDefinitionHolder> parse(AnnotationAttributes componentScan, final String declaringClass) {
        // 定义了一个类路径扫描器ClassPathBeanDefinitionScanner
        // 这里的scanner用于读取配置类
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

        // 1. 判断是否有nameGenerator注解
        // 为扫描器设置beanName的生成器对象
        Class<? extends BeanNameGenerator> generatorClass = componentScan.getClass("nameGenerator");
        boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
        scanner.setBeanNameGenerator(useInheritedGenerator ? this.beanNameGenerator :
                BeanUtils.instantiateClass(generatorClass));

        // 2. 判断是否有scopedProxy注解
        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));
        }

        scanner.setResourcePattern(componentScan.getString("resourcePattern"));

        // 3. 判断属性中是否有includeFilters属性, 有的话就添加到scanner中
        // 设置componentScan中包含的过滤器 -- 在使用注解的时候配置了包含和排除的过滤器, 这里进行处理
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addIncludeFilter(typeFilter);
            }
        }

        // 4. 判断属性总是否有excludeFilters属性, 有的话放到scnanner中
        // 设置componentScan中排除的过滤器
        for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
            for (TypeFilter typeFilter : typeFiltersFor(filter)) {
                scanner.addExcludeFilter(typeFilter);
            }
        }

        // 5. 判断是否有lazyInit属性
        // 获取配置类中懒加载初始化的属性
        boolean lazyInit = componentScan.getBoolean("lazyInit");
        if (lazyInit) {
            scanner.getBeanDefinitionDefaults().setLazyInit(true);
        }

        Set<String> basePackages = new LinkedHashSet<>();

        // 6. 判断是否有basePackages属性
        // 获取basePackages属性, 也就是我们定义的包扫描路径
        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));
        }

         // 想ExcludeFilter中添加默认的排除类,
        scanner.addExcludeFilter(new AbstractTypeHierarchyTraversingFilter(false, false) {
            @Override
            protected boolean matchClassName(String className) {
                /**
                 * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉
                 * 这是一个钩子方法, 现在不会调用. 后面才调用
                 * 在哪里调用呢?
                  */
                return declaringClass.equals(className);
            }
        }); // 调用scanner.doScan()方法, 扫描basePackages包
        return scanner.doScan(StringUtils.toStringArray(basePackages));
    }

复制代码

在解析配置类的时候, 除了@ComponentScan注解中定义的ExcludeFilter和IncludeFilter以外, 还有默认的排除类. 如上加粗字体的部分. 这里是排除了配置类本身, 我们这里的配置类是MainConfig, 也就说, 会排除掉自己. 

复制代码

       @Override
            protected boolean matchClassName(String className) {
                /**
                 * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉
                 * 这是一个钩子方法, 现在不会调用. 后面才调用
                 * 在哪里调用呢? 先记住这个钩子方法matchClassName
                  */
                return declaringClass.equals(className);
            }

复制代码

matchClassName是一个钩子方法. 在执行到这里的时候, 不会真的去执行. 什么时候执行呢? 后面调用doScan的时候执行.

复制代码

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        Assert.notEmpty(basePackages, "At least one base package must be specified");
        Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
        // 循环包路径
        for (String basePackage : basePackages) {
             // 第一步: 找到所有候选的BeanDefinition
            /**
             * 在候选的配置类中, 排除掉了自己, 同时包含了默认的配置类
             */ Set<BeanDefinition> candidates = findCandidateComponents(basePackage); 

复制代码

在寻找候选配置类的时候, 进行了排除了配置类本身.
复制代码

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
            return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
        }
        else {
             // 扫描basePackages, 获取候选类
            return scanCandidateComponents(basePackage); 
        }
    }

复制代码

进入这个方法

复制代码

private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<>();
        try {
            //第一步:  将com.lxl.www.iocbeanlifecicle转换成了物理路径com/lxl/www/iocbeanlifecicle
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                    resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            //第二步:  .getResources(...)读取到了包下所有的类
            Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
            boolean traceEnabled = logger.isTraceEnabled();
            boolean debugEnabled = logger.isDebugEnabled();
            for (Resource resource : resources) {
                if (traceEnabled) {
                    logger.trace("Scanning " + resource);
                }
                //第三步:  判断这个类是否是可读的?
                if (resource.isReadable()) {
                    try {
                        MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                         //第四步:  判断这个类是否是我们要排除的 或者 包含的
                       if (isCandidateComponent(metadataReader)) { // 通过scnner扫描出来的beanDefinition是ScannedGenericBeanDefinition类型
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            // 设置sbd的原类路径
                            sbd.setSource(resource);

复制代码

在第四步的时候调用了isCandidateComponent(metadataReader, 这里就判断了是否是包含的类,或者是排除的类

复制代码

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        // 判断这个类类是否是我们设置的要排除的?
        // 这里依然使用到了策略设计模式. TypeFilter是一个父类, 不同子类的TypeFilter会调用不同的match方法
        for (TypeFilter tf : this.excludeFilters) {
            // 在这里面排除类配置类本身
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return false;
            }
        } // 判断这个类是否是我们要包含的?
        for (TypeFilter tf : this.includeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return isConditionMatch(metadataReader);
            }
        } return false;
    }

复制代码

紫色加错的部分是就是判读是否符合排除的类. 红色加错的部分是判断是否是包含的类. 

先来看紫色的部分, 排除的类

复制代码

@Override
    public boolean  match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
            throws IOException {

        // This method optimizes avoiding unnecessary creation of ClassReaders
        // as well as visiting over those readers.
        if (matchSelf(metadataReader)) {
            return true;
        }
        ClassMetadata metadata = metadataReader.getClassMetadata();
         // 排除配置类.
        if (matchClassName(metadata.getClassName())) {
            return true;
        } 

复制代码

看到了么, 这里调用了matchClassName. 这就是上面定义的钩子方法, 

复制代码

        @Override
            protected boolean matchClassName(String className) {
                /**
                 * declaringClass就是配置类MainConfig, 也就是说. 如果当前类是配置类, 那么就会排除掉
                 * 这是一个钩子方法, 现在不会调用. 后面才调用
                 * 在哪里调用呢? 先记住这个钩子方法matchClassName
                  */
                return declaringClass.equals(className);
            }

复制代码

此时declaringClass表示的是当前的配置类, className表示的是目标类, 如果当前目标类 == 配置类, 那么就放回true. 返回true, 则会排除掉

 

  1. includeFilter中包含了默认的配置类

下面来看红色加错的部分

复制代码

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
        // 判断这个类类是否是我们设置的要排除的?
        // 这里依然使用到了策略设计模式. TypeFilter是一个父类, 不同子类的TypeFilter会调用不同的match方法
        for (TypeFilter tf : this.excludeFilters) {
            // 在这里面排除类配置类本身
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return false;
            }
        } // 判断这个类是否是我们要包含的?
        for (TypeFilter tf : this.includeFilters) {
            if (tf.match(metadataReader, getMetadataReaderFactory())) {
                return isConditionMatch(metadataReader);
            }
        } return false;
    }

复制代码

我们看到这里有this.includeFilters.包含的过滤器. 这里面是有值的

 

 我们没有在配置类MainConfig上设置includeFilter啊, 这里面怎么会有值呢?

这是因为我们有默认包含的过滤器, 下面看看默认包含的过滤器是在哪里设置的.

首先从入口类点击AnnotationConfigApplicationContextxt

 

然后在点击this();

 

再点击ClassPathBeanDefinitionScanner

 

 然后一路点击三个this(...)

 

 最后看到上图 registerDefaultFilter();注册默认的过滤器

 

复制代码

@SuppressWarnings("unchecked")
    protected void registerDefaultFilters() {
         // 注册默认的filter---第一个: 在includeFilter中增加了Component
        this.includeFilters.add(new AnnotationTypeFilter(Component.class )); 
        ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
        try {
             // 注册默认的filter---第二个:在includeFilter中增加了 javax.annotation.ManagedBean
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false ));
            logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
            // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
        }
        try {
             // 注册默认的filter---第三个:在includeFilter中增加了 javax.inject.Named
            this.includeFilters.add(new AnnotationTypeFilter(
                    ((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false )); 
            logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
        }
        catch (ClassNotFoundException ex) {
            // JSR-330 API not available - simply skip.
        }
    }

复制代码

如上图看到, 注册了3个默认的过滤器. 分别是Component, ManagedBean, Named. 他们都是注解类型的过滤器AnnotationTypeFilter

其中javax.annotation.ManagedBean和 javax.inject.Named是jdk提供给我们的.

 

 

 

到此为止, 就将MainConfig配置类解析完并注册到ioc容器中了.