• 07-Spring ConfigurationClassPostProcessor


    ConfigurationClassPostProcessor

    功能

    此类是一个后置处理器类,主要功能是参与 BeanFactory 中 BeanDefinition 的操作和 BeanDefinition 中属性值的修改。主要用于解析注解。

    1. 解析加了@Configuration的配置类
    2. 解析@ComponentScan扫描的包
    3. 解析@ComponentScans扫描的包
    4. 解析@Import注解

    通过此类的类图可以看到其实现了 BeanDefinitionRegistryPostProcessor 接口,所以会在 invokeBeanFactoryPostProcessors(beanFactory) 的时候进行调用。

    注入位置

    只要开启了注解扫描 <context:component-scan base-package="com.baiying.config" ></context:component-scan>,或者 <context:annotation-config/> 都会触发其注入,主要是调用其AnnotationConfigUtils.registerAnnotationConfigProcessors 来进行类的注入,具体的逻辑,参考Spring自定义标签解析

    定位、加载、解析、注册相关注解

    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常
        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);
        }
        // 将马上要进行处理的registry对象的id值放到已经处理的集合对象中
        this.registriesPostProcessed.add(registryId);
    
        // 处理配置类的bean定义信息
        processConfigBeanDefinitions(registry);
    }
    

    processConfigBeanDefinitions(registry)

    构建和解析一个类是否被 @Configuration 修饰,如果是被 @Configuration 注解标注,同时属性proxyBeanMethods 为 false,则将 beanDefinition 标记为 full。

    如果 bean 被 @Configuration 注解标注,且同时被 @Component 、@ComponentScan、@Import、@ImportResource、@Bean 标记的方法会被标记为 lite。

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
        // 创建存放BeanDefinitionHolder的对象集合
        List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
        // 当前registry就是DefaultListableBeanFactory,获取所有已经注册的BeanDefinition的beanName
        String[] candidateNames = registry.getBeanDefinitionNames();
    
        // 遍历所有要处理的beanDefinition的名称,筛选对应的beanDefinition(被注解修饰的)
        for (String beanName : candidateNames) {
            // 获取指定名称的BeanDefinition对象
            BeanDefinition beanDef = registry.getBeanDefinition(beanName);
            // 如果beanDefinition中的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);
                }
            }
            // 判断当前BeanDefinition是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
            // 如果Configuration配置proxyBeanMethods代理为true则为full
            // 如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
            // 如果配置类上被@Order注解标注,则设置BeanDefinition的order属性值
            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
        // 如果适用,则按照先前确定的@Order的值排序
        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类型
        SingletonBeanRegistry sbr = null;
        if (registry instanceof SingletonBeanRegistry) {
            // 类型的强制转换
            sbr = (SingletonBeanRegistry) registry;
            // 判断是否有自定义的beanName生成器
            if (!this.localBeanNameGeneratorSet) {
                // 获取自定义的beanName生成器
                BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
                // 如果有自定义的命名生成策略
                if (generator != null) {
                    //设置组件扫描的beanName生成策略
                    this.componentScanBeanNameGenerator = generator;
                    // 设置import bean name生成策略
                    this.importBeanNameGenerator = generator;
                }
            }
        }
    
        // 如果环境对象等于空,那么就重新创建新的环境对象
        if (this.environment == null) {
            this.environment = new StandardEnvironment();
        }
    
        // Parse each @Configuration class
        // 实例化ConfigurationClassParser类,并初始化相关的参数,完成配置类的解析工作
        ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);
    
        // 创建两个集合对象,
        // 存放相关的BeanDefinitionHolder对象
        Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
        // 存放扫描包下的所有bean
        Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
        do {
            // 解析带有@Controller、@Import、@ImportResource、@ComponentScan、@ComponentScans、@Bean的BeanDefinition
            parser.parse(candidates);
            // 将解析完的Configuration配置类进行校验,1、配置类不能是final,2、@Bean修饰的方法必须可以重写以支持CGLIB
            parser.validate();
    
            // 获取所有的bean,包括扫描的bean对象,@Import导入的bean对象
            Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
            // 清除掉已经解析处理过的配置类
            configClasses.removeAll(alreadyParsed);
    
            // Read the model and create bean definitions based on its content
            // 判断读取器是否为空,如果为空的话,就创建完全填充好的ConfigurationClass实例的读取器
            if (this.reader == null) {
                this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
            }
            // 核心方法,将完全填充好的ConfigurationClass实例转化为BeanDefinition注册入IOC容器
            this.reader.loadBeanDefinitions(configClasses);
            // 添加到已经处理的集合中
            alreadyParsed.addAll(configClasses);
    
            candidates.clear();
            // 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加新的BeanDefinition
            // 实际上就是看配置类(例如AppConfig类会向BeanDefinitionMap中添加bean)
            // 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length
            // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析
            // 这里的AppConfig类向容器中添加的bean,实际上在parser.parse()这一步已经全部被解析了
            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());
                }
                // 如果有未解析的类,则将其添加到candidates中,这样candidates不为空,就会进入到下一次的while的循环中
                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();
        }
    }
    

    ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory))

    public static boolean checkConfigurationClassCandidate(
        BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
    
        // 获取bean定义信息中的class类名
        String className = beanDef.getBeanClassName();
        // 如果className为空,或者bean定义信息中的factoryMethod不等于空,那么直接返回
        if (className == null || beanDef.getFactoryMethodName() != null) {
            return false;
        }
    
        AnnotationMetadata metadata;
        // 通过注解注入的db都是AnnotatedGenericBeanDefinition,实现了AnnotatedBeanDefinition
        // spring内部的bd是RootBeanDefinition,实现了AbstractBeanDefinition
        // 此处主要用于判断是否归属于AnnotatedBeanDefinition
        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();
        }
        // 判断是否是spring中默认的BeanDefinition
        else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
            // Check already loaded Class if present...
            // since we possibly can't even load the class file for this Class.
            // 获取当前bean对象的Class对象
            Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
            // 如果class实例是下面四种类或接口的子类、父接口等任何一种情况,直接返回
            if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
                BeanPostProcessor.class.isAssignableFrom(beanClass) ||
                AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
                EventListenerFactory.class.isAssignableFrom(beanClass)) {
                return false;
            }
            // 为给定类创建新的AnnotationMetadata实例
            metadata = AnnotationMetadata.introspect(beanClass);
        }
        // 如果上述两种情况都不符合
        else {
            try {
                // 获取className的MetadataReader实例
                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;
            }
        }
    
        // 获取bean定义的元数据被@Configuration注解标注的属性字典值
        Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
        // 如果bean被@Configuration注解标注,且属性proxyBeanMethods为false(使用代理模式),则将bean定义记为full
        if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        // 如果bean被@configuration注解标注,且被注解@Component,@ComponentScan、@Import、@ImportResource或者@Bean标记的方法,则将bean定义标记为lite
        else if (config != null || isConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }
        else {
            return false;
        }
    
        // It's a full or lite configuration candidate... Let's determine the order value, if any.
        // bean定义是一个标记为full或lite的候选项,如果设置order则设置order属性值
        Integer order = getOrder(metadata);
        // 如果值不为空的话,那么直接设置值到具体的beanDefinition
        if (order != null) {
            // 设置bean定义的order值
            beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }
    
        return true;
    }
    

    ConfigurationClassParser.parse()解析

    parse()方法是一个重载方法,会调用下一步里面 processConfigurationClass()方法。

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        // 循环遍历configCandidates
        for (BeanDefinitionHolder holder : configCandidates) {
            // 获取BeanDefinition
            BeanDefinition bd = holder.getBeanDefinition();
            // 根据BeanDefinition类型的不同,调用parse不同的重载方法,实际上最终都是调用processConfigurationClass()方法
            try {
                // 注解类型
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                // 有class对象的
                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);
            }
        }
    
        // 执行找到的DeferredImportSelector
        // DeferredImportSelector是ImportSelector的一个子类
        // ImportSelector被设计成和@Import注解同样的效果,但是实现了ImportSelector的类可以条件性的决定导入某些配置
        // DeferredImportSelector的设计模式是在所有其他的配置类被处理后才进行处理
        this.deferredImportSelectorHandler.process();
    }
    

    processConfigurationClass

    shouldSkip:基于 @Conditional 注解判断是否需要跳过解析。

    protected void  processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        // 判断是否跳过解析
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
    
        // 第一次进入的时候,configurationClass的size为0,existingClass肯定为null,在此处处理configuration重复import
        // 如果同一个配置类被处理两次,两次都属于被import的则合并导入类,返回,如果配置类不是被导入的,则移除旧的使用新的配置类
        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                if (existingClass.isImported()) {
                    // 如果要处理的配置类configclass在已经分析处理的配置类记录中已存在,合并两者的importBy属性
                    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.
    
        // 处理配置类,由于配置类可能存在父类(若父类的全类名是以java开头的,则除外),所有需要将configClass变成sourceClass去解析,然后返回sourceClass的父类。
        // 如果此时父类为空,则不会进行while循环去解析,如果父类不为空,则会循环的去解析父类
        // SourceClass的意义:简单的包装类,目的是为了以统一的方式去处理带有注解的类,不管这些类是如何加载的
        // 如果无法理解,可以把它当做一个黑盒,不会影响看spring源码的主流程
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
            // 解析各种注解
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);
    
        // 将解析的配置类存储起来,这样回到parse方法时,能取到值
        this.configurationClasses.put(configClass, configClass);
    }
    

    doProcessConfigurationClass(configClass, sourceClass, filter)

    真正解析的方法,处理各种注解,@Component、@PropertySource、@ComponentScans、@ComponentScan、@Import、@ImportResource,以及内部类和接口等。

    protected final SourceClass doProcessConfigurationClass(
        ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter)
        throws IOException {
        // @Configuration继承了@Component
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // Recursively process any member (nested) classes first
            // 递归处理内部类,因为内部类也是一个配置类,配置类上有@configuration注解,该注解继承@Component,if判断为true,调用processMemberClasses方法,递归解析配置类中的内部类
            processMemberClasses(configClass, sourceClass, filter);
        }
    
        // Process any @PropertySource annotations
        // 如果配置类上加了@PropertySource注解,那么就解析加载properties文件,并将属性添加到spring上下文中
        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
        // 处理@ComponentScan或者@ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass
        // 此处就是将自定义的bean加载到IOC容器,因为扫描到的类可能也添加了@ComponentScan和@ComponentScans注解,因此需要进行递归解析
        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
                // 解析@ComponentScan和@ComponentScans配置的扫描的包所包含的类
                // 比如 basePackages = com.mashibing, 那么在这一步会扫描出这个包及子包下的class,然后将其解析成BeanDefinition
                // (BeanDefinition可以理解为等价于BeanDefinitionHolder)
                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
                // 通过上一步扫描包com.mashibing,有可能扫描出来的bean中可能也添加了ComponentScan或者ComponentScans注解.
                //所以这里需要循环遍历一次,进行递归(parse),继续解析,直到解析出的类上没有ComponentScan和ComponentScans
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    // 判断是否是一个配置类,并设置full或lite属性
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        // 通过递归方法进行解析
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }
    
        // Process any @Import annotations
        // 处理@Import注解
        processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
    
        // Process any @ImportResource annotations
        // 处理@ImportResource注解,导入spring的配置文件
        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
        // 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }
    
        // Process default methods on interfaces
        // 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析
        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;
    }
    

    getImports(sourceClass)

    获取所有导入的类,会进行递归调用。

    processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

    private void processImports(ConfigurationClass configClass, SourceClass currentSourceClass,
    Collection<SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
    
        // 如果使用@Import注解修饰的类集合为空,那么直接返回
        if (importCandidates.isEmpty()) {
            return;
        }
        // 通过一个栈结构解决循环引入
        if (checkForCircularImports && isChainedImportOnStack(configClass)) {
            this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
        }
        else {
            // 添加到栈中,用于处理循环引入的问题
            this.importStack.push(configClass);
            try {
                // 遍历每一个@Import注解的类
                for (SourceClass candidate : importCandidates) {
                    // 检验配置类Import引入的类是否是ImportSelector子类
                    if (candidate.isAssignable(ImportSelector.class)) {
                        // Candidate class is an ImportSelector -> delegate to it to determine imports
                        // 候选类是一个导入选择器->委托来确定是否进行导入
                        Class<?> candidateClass = candidate.loadClass();
                        // 通过反射生成一个ImportSelect对象
                        ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,
                                                                                       this.environment, this.resourceLoader, this.registry);
                        // 获取选择器的额外过滤器
                        Predicate<String> selectorFilter = selector.getExclusionFilter();
                        if (selectorFilter != null) {
                            exclusionFilter = exclusionFilter.or(selectorFilter);
                        }
                        // 判断引用选择器是否是DeferredImportSelector接口的实例
                        // 如果是则应用选择器将会在所有的配置类都加载完毕后加载
                        if (selector instanceof DeferredImportSelector) {
                            // 将选择器添加到deferredImportSelectorHandler实例中,预留到所有的配置类加载完成后统一处理自动化配置类
                            this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);
                        }
                        else {
                            // 获取引入的类,然后使用递归方式将这些类中同样添加了@Import注解引用的类
                            String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                            Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);
                            // 递归处理,被Import进来的类也有可能@Import注解
                            processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                        }
                    }
                    // 如果是实现了ImportBeanDefinitionRegistrar接口的bd
                    else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
                        // Candidate class is an ImportBeanDefinitionRegistrar ->
                        // delegate to it to register additional bean definitions
                        // 候选类是ImportBeanDefinitionRegistrar  -> 委托给当前注册器注册其他bean
                        Class<?> candidateClass = candidate.loadClass();
                        ImportBeanDefinitionRegistrar registrar =
                            ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class,
                                                                 this.environment, this.resourceLoader, this.registry);
                        /**
    						 * 放到当前configClass的importBeanDefinitionRegistrars中
    						 * 在ConfigurationClassPostProcessor处理configClass时会随之一起处理
    						 */
                        configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                    }
                    else {
                        // Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->
                        // process it as an @Configuration class
                        // 候选类既不是ImportSelector也不是ImportBeanDefinitionRegistrar-->将其作为@Configuration配置类处理
                        this.importStack.registerImport(
                            currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
                        /**
    						 * 如果Import的类型是普通类,则将其当作带有@Configuration的类一样处理
    						 * 将candidate构造为ConfigurationClass,标注为importedBy,意味着它是通过被@Import进来的
    						 * 后面处理会用到这个判断将这个普通类注册进DefaultListableBeanFactory
    						 */
                        processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                    }
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configClass.getMetadata().getClassName() + "]", ex);
            }
            finally {
                this.importStack.pop();
            }
        }
    }
    

    this.reader.loadBeanDefinitions(configClasses)

    ConfigurationClassBeanDefinitionReader#reader,此处会将所有注解标注的类,注入到 IOC中。

  • 相关阅读:
    [python2] python 打印表格 prettytable
    多条件查询
    excel模板导出一个新的文件
    通过反射的形式把集合的数据打印到log里
    C#写入log文本
    EF删除所有数据行的方法.所以下面给大家介绍几种方法.
    一种批量导出的方式
    一种简单的导出导入希望大神别介意
    excel导出
    excel的模板
  • 原文地址:https://www.cnblogs.com/ice-image/p/14543414.html
Copyright © 2020-2023  润新知