Spring 之 ConfigurationClassPostProcessor

Spring 之 ConfigurationClassPostProcessor

 

 

1、简介
ConfigurationClassPostProcessor 是一个后置处理器的类,主要功能是参与BeanFactory的建造,主要功能如下:

  • 解析加了@Configuration的配置类。
  • 解析@ComponentScan扫描的包。
  • 解析@ComponentScans扫描的包。
  • 解析@Import注解。
  • 解析了 @PropertySource 注解。
  • 解析了 @ImportResource 注解。
  • 解析了 @Bean 方法。

ConfigurationClassPostProcessor 类图关系:

ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 接口,而 BeanDefinitionRegistryPostProcessor 接口继承了 BeanFactoryPostProcessor 接口,所以 ConfigurationClassPostProcessor 中需要重写 postProcessBeanDefinitionRegistry() 和 postProcessBeanFactory() 方法。从这两个方法的名称就能看出一个是针对BeanDefinition的后置处理, 另外一个是针对BeanFactory的后置处理。这两个方法在 ConfigurationClassPostProcessor 中的主要作用如下:

  1. postProcessBeanDefinitionRegistry()方法: 定位、加载、解析、注册相关注解。
  2. postProcessBeanFactory()方法: 添加CGLIB增强处理及ImportAwareBeanPostProcessor后置处理类。

 

2、ConfigurationClassPostProcessor注入时机
Spring源码会在创建AnnotationConfigApplicationContext容器的时候,会去创建AnnotatedBeanDefinitionReader。

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
        // 实例化Bean相关的处理器
        this();
        register(componentClasses);
        refresh();
    }

    public AnnotationConfigApplicationContext() {
       // 实例化注解 Bean 定义解析器
        this.reader = new AnnotatedBeanDefinitionReader(this);
        // 实例化类路径 Bean 扫描器
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

在创建AnnotatedBeanDefinitionReader的过程中会去注入注解相关的后置处理器:

  public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
            this(registry, getOrCreateEnvironment(registry));
        }
        
    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        Assert.notNull(environment, "Environment must not be null");
        this.registry = registry;
        this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
        // 注册注解相关的后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

org.springframework.context.annotation.AnnotationConfigUtils

public abstract class AnnotationConfigUtils {
    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, @Nullable Object source) {

        // 省略部分代码....

        // 创建BeanDefinitionHolder集合
        Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);

        // 1、注册ConfigurationClassPostProcessor,用于处理 @configuration、@ComponentScan、@Import 注解的后置处理器的bean
        if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // 2、注册AutowiredAnnotationBeanPostProcessor,用于处理@Autowired,@Value, @Inject以及@Lookup注解的后置处理器bean
        if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // 3、注册CommonAnnotationBeanPostProcessor 用于处理JSR-250注解,例如@Resource, @PostConstruct, @PreDestroy的后置处理器bean
        if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // 4、注册PersistenceAnnotationBeanPostProcessor 用于处理JPA注解的后置处理器bean
        if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition();
            try {
                def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                        AnnotationConfigUtils.class.getClassLoader()));
            }
            catch (ClassNotFoundException ex) {
                throw new IllegalStateException(
                        "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
            }
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
        }

        // 5、注册EventListenerMethodProcessor 用于处理@EventListener注解的后置处理器的bean
        if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
        }

        // 6、注册DefaultEventListenerFactory 用于生产ApplicationListener对象的EventListenerFactory对象
        if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
        }

        return beanDefs;
    }
}

 

3、ConfigurationClassPostProcessor 源码解析
ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)方法是优先于ConfigurationClassPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 执行的。
这两个方法的执行是在org.springframework.context.support.AbstractApplicationContext.refresh()--> invokeBeanFactoryPostProcessors()方法中执行的。
3.1、下面我们直接到ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry()方法中:
此方法主要完成对@Configuration注解标注的BeanDefinition解析,同时解析出 @ComponentScan 和 @ComponentScans 扫描出的Bean,也会解析出加了@Bean 注解的方法所注册的Bean,以及通过 @Import 注解注册的Bean 和 @ImportResource 注解导入的配置文件中配置的Bean。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
     /**
     * 定位、加载、解析、注册相关注解
     */
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        // 根据对应的registry对象生成hashcode值,此对象只会操作一次,如果之前处理过则抛出异常
        int registryId = System.identityHashCode(registry);
        
        // 将马上要进行处理的registry对象的id值放到已经处理的集合对象中
        this.registriesPostProcessed.add(registryId);

        // 处理配置类的bean定义信息
        processConfigBeanDefinitions(registry);
    }
}

处理配置类的bean定义信息方法:

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
        PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
    /**
     * 构建和验证一个类是否被@Configuration修饰,并做相关的解析工作
     * 如果你对此方法了解清楚了,那么Springboot的自动装配原理就清楚了
     */
    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是否是一个配置类,并为BeanDefinition设置属性为lite或者full,此处设置属性值是为了后续进行调用
            // 如果Bean被 @Configuration 注解标记则为full。如果加了@Bean、@Component、@ComponentScan、@Import、@ImportResource注解,则设置为lite
            // 如果配置类上被 @Order注解标注,则设置BeanDefinition的order属性值
            if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
                // 添加候选解析类到集合中
                configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
            }
        }
        // 根据注册Bean 的 @Order 优先级排序 
        configCandidates.sort((bd1, bd2) -> {
            int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
            int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
            return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
        });
        
        //----------------第二步-----------------
        // 解析每一个被 @Configuration注解标记的Class
        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
// 实际上就是看配置类(例如XXXConfig类会向BeanDefinitionMap中添加bean) // 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析 // 这里的XXXConfig类向容器中添加的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()); } }

 

第一步,筛选出被@Configuration注解标注的BeanDefinition
遍历容器中的BeanDefinitionNames集合,找出来被@Configuration标注的BeanDefinition并加入到代处理集合configCandidates中。如果Bean注解了 @Configuration 则标记为full。
如果Bean不是接口、并且被@Component、@ComponentScan、@Import、@ImportResource 注解标记,则记为lite。
主要由ConfigurationClassUtils.checkConfigurationClassCandidate()方法来完成:

abstract class ConfigurationClassUtils {
    public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
        String className = beanDef.getBeanClassName();
        if (className == null || beanDef.getFactoryMethodName() != null) {
            return false;
        }
        // .... 省略
      
        // 如果注解了 @Configuration 则标记为full
        if (isFullConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        // 如果不是接口、并且被@Component、@ComponentScan、@Import、@ImportResource 注解标记,则记为lite
        else if (isLiteConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        } else {
            return false;
        }

        // 设置处理的优先级
        Integer order = getOrder(metadata);
        if (order != null) {
            beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }
        return true;
    }
}

 

第二步,解析被@Configuration注解标注的BeanDefinition。获取所有的bean对象放入configClasses集合里面。
主要是由ConfigurationClassParser#paser()方法来完成的:

class ConfigurationClassParser {
    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());
                }
            }
        }
    }
    
    
    protected void processConfigurationClass(ConfigurationClass configClass) throws IOException {
        // 解析 @Conditional 注解看是否需要跳过该Bean
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }
            // ... 省略
            
        // 递归处理配置类及其超类层次结构
        SourceClass sourceClass = asSourceClass(configClass);
        do {
            sourceClass = doProcessConfigurationClass(configClass, sourceClass);
        }
        while (sourceClass != null);

        this.configurationClasses.put(configClass, configClass);
    }
    
    
    protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass)
            throws IOException {
        
        // 递归解析配置类中的内部类
        processMemberClasses(configClass, sourceClass);

        // 如果配置类上加了@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.warn("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // 处理 @ComponentScan 或者 @ComponentScans注解,并将扫描包下的所有bean转换成填充后的ConfigurationClass
        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) {
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(
                            holder.getBeanDefinition(), this.metadataReaderFactory)) {
                        parse(holder.getBeanDefinition().getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // 处理@Import注解
        processImports(configClass, sourceClass, getImports(sourceClass), true);

        // 处理@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);
            }
        }

        // 处理加了@Bean注解的方法,将@Bean方法转化为BeanMethod对象,保存再集合中
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

    // 处理接口的默认方法实现,从jdk8开始,接口中的方法可以有自己的默认实现,因此如果这个接口的方法加了@Bean注解,也需要被解析
        processInterfaces(configClass, sourceClass);

        // 解析父类,如果被解析的配置类继承了某个类,那么配置类的父类也会被进行解析
        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;
    }
}

 

第三步,将扫描到的所有beanDefinition注册到容器的BeanDefinitionMap中
将第二步中扫描到的所有bean(在configClasses中存放着),注入到容器的BeanDefinitionMap中,完成导入bean的注入工作。

class ConfigurationClassBeanDefinitionReader {
    
    public void loadBeanDefinitions(Set<ConfigurationClass> configurationModel) {
        TrackedConditionEvaluator trackedConditionEvaluator = new TrackedConditionEvaluator();
        for (ConfigurationClass configClass : configurationModel) {
            // 循环调用loadBeanDefinitionsForConfigurationClass方法
            loadBeanDefinitionsForConfigurationClass(configClass, trackedConditionEvaluator);
        }
    }
    
    /**
     * 读取一个单独的ConfigurationClass类,注册bean本身(@Import引入的普通类)或者@Configuration配置类的Bean方法
     */
    private void loadBeanDefinitionsForConfigurationClass(
            ConfigurationClass configClass, TrackedConditionEvaluator trackedConditionEvaluator) {
         // ... 省略
        
        // 如果一个bean是通过@Import(ImportSelector)的方式添加到容器中的,那么此时configClass.isImported()返回的是true
        // 而且configClass的importedBy属性里面存储的是ConfigurationClass就是将bean导入的类
        if (configClass.isImported()) {
            registerBeanDefinitionForImportedConfigurationClass(configClass);
        }
        // 判断当前的bean中是否含有@Bean注解的方法,如果有,需要把这些方法产生的bean放入到BeanDefinitionMap当中
        for (BeanMethod beanMethod : configClass.getBeanMethods()) {
            loadBeanDefinitionsForBeanMethod(beanMethod);
        }

        // 将@ImportResource引入的资源注入IOC容器
        loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
        
        // 如果bean上存在@Import注解,且import的是一个实现了ImportBeanDefinitionRegistrar接口,
        //则执行ImportBeanDefinitionRegistrar的registerBeanDefinitions()方法
        loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
    }
}

 

第四步,判断第三步中注入到BeanDefinitionMap中BeanDefinition是否已经被解析过,如果没有被解析过,那么需要继续解析:

// 这里判断registry.getBeanDefinitionCount() > candidateNames.length的目的是为了知道reader.loadBeanDefinitions(configClasses)这一步有没有向BeanDefinitionMap中添加
// 新的BeanDefinition
// 如果有,registry.getBeanDefinitionCount()就会大于candidateNames.length // 这样就需要再次遍历新加入的BeanDefinition,并判断这些bean是否已经被解析过了,如果未解析,需要重新进行解析 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; }

 

3.2、postProcessBeanFactory() 方法
ConfigurationClassPostProcessor#postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)方法的执行也是在invokeBeanFactoryPostProcessors()方法中执行的
此方法主要是对被@Configuration注解标注的类添加CGLIB增强处理以及添加ImportAwareBeanPostProcessor后置处理。
下面我们直接到ConfigurationClassPostProcessor#postProcessBeanFactory()方法中:

    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        int factoryId = System.identityHashCode(beanFactory);
        
        // 如果还没执行解析工作,则先去执行processConfigBeanDefinitions进行解析
        this.factoriesPostProcessed.add(factoryId);
        if (!this.registriesPostProcessed.contains(factoryId)) {
            processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
        }
        // 对当前容器中被@Configuration注解标注的BeanDefinition进行CGLIb增强(即标记为Full的Bean),目的是为了解决@Bean单例问题。
        enhanceConfigurationClasses(beanFactory);
        // 添加ImportAwareBeanPostProcessor后置处理器
        beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
    }

 

4、总结
ConfigurationClassPostProcessor类是用来对@Configuration注解标注的BeanDefinition来处理的。
postProcessBeanDefinitionRegistry()方法是解析@Configuration注解标注的BeanDefinition,同时解析出@ComponentScan和@ComponentScans扫描出的Bean,也会解析出加了@Bean注解的方法所注册的Bean,以及通过 @Import 注解注册的Bean和 @ImportResource 注解导入的配置文件中配置的Bean。
postProcessBeanFactory()方法对加了@Configuration注解修饰的类都会被spring代理,目的是为了解决@Bean单例问题。子类会重写@Bean方法,来保证bean是单例的。

 

posted @ 2024-01-03 10:43  邓维-java  阅读(597)  评论(0)    收藏  举报