您当前的位置: 首页 >  spring

止步前行

暂无认证

  • 0浏览

    0关注

    247博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring源码系列(四)——ConfigurationClassPostProcessor功能解析

止步前行 发布时间:2021-10-24 16:05:05 ,浏览量:0

文章目录
  • 一、postProcessBeanDefinitionRegistry()
    • 1. processConfigBeanDefinitions()
    • 2. parser.parse()
    • 3. processConfigurationClass()(重点!!!)
    • 4. doProcessConfigurationClass()
    • 5. parse()
    • 6. doScan()
    • 7. 小结
  • 二、postProcessBeanFactory()
    • 1. enhanceConfigurationClasses()
    • 2. enhance()
    • 3. newEnhancer()
    • 4. createClass()
    • 5.小结

此篇文章主要分析ConfigurationClassPostProcessor类的两个方法作用,分别是:

  • postProcessBeanDefinitionRegistry()
  • postProcessBeanFactory()

经过前面第三篇的分析,从PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());方法的入口,下面先来分析此方法中的第二个知识点,即下面这行代码:

// 这个currentRegistryProcessors 存放的是spring内部自己实现了BeanDefinitionRegistryPostProcessor接口的对象
List currentRegistryProcessors = new ArrayList();

// 调用实现BeanDefinitionRegistryPostProcessor接口的类
// 下面这行代码在PostProcessorRegistrationDelegate类中invokeBeanFactoryPostProcessors()
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);

此行代码会执行到ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry()方法。

一、postProcessBeanDefinitionRegistry()

此方法为接口BeanDefinitionRegistryPostProcessor中的方法。

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
    int registryId = System.identityHashCode(registry);

    // 将registryId放入registriesPostProcessed中,在postProcessBeanFactory()方法中就不会再执行
    this.registriesPostProcessed.add(registryId);
    
    // 根据方法名,顾名思义,处理配置Bean,详细介绍看下面第1小点
    processConfigBeanDefinitions(registry);
}
1. processConfigBeanDefinitions()

此方法的作用就是处理配置类,重要部分在parser.parse(candidates);这一行。

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    
    // 存放appConfig提供的BeanDefinition
    List configCandidates = new ArrayList();
    
    // 获取容器中注册的所有BeanDefinition名字,7个,6个spring内部提供的,一个配置类appConfig
    String[] candidateNames = registry.getBeanDefinitionNames();

    // Full or Lite
    for (String beanName : candidateNames) {
        // 根据beanName,拿到BeanDefinition
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        // 根据BeanDefinition里面的class属性来判断
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
            // 如果BeanDefinition中的configurationClass属性为full或者lite,则意味着已经处理过了,直接跳过
        } else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            // 判断是不是Configuration类,如果加了Configuration注解的就是FULL
            // 如果是下面四个注解就是Lite
            // candidateIndicators.add(Component.class.getName());
            // candidateIndicators.add(ComponentScan.class.getName());
            // candidateIndicators.add(Import.class.getName());
            // candidateIndicators.add(ImportResource.class.getName());
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    if (configCandidates.isEmpty()) {
        return;
    }

    // 排序,根据order,不重要
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    SingletonBeanRegistry sbr = null;
    // 如果BeanDefinitionRegistry是SingletonBeanRegistry子类的话,
    // 由于我们当前传入的是DefaultListableBeanFactory,是SingletonBeanRegistry 的子类
    // 因此会将registry强转为SingletonBeanRegistry
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        if (!this.localBeanNameGeneratorSet) {
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
            // SingletonBeanRegistry中有id为 org.springframework.context.annotation.internalConfigurationBeanNameGenerator
            // 如果有则利用它的,否则则是Spring默认的
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

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

    // 实例化ConfigurationClassParser 为了解析各个配置类
    ConfigurationClassParser parser = new ConfigurationClassParser(
        this.metadataReaderFactory, this.problemReporter, this.environment,
        this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    // 实例化两个集合,candidates用于将之前加入的configCandidates进行去重,因为可能有多个配置类重复了
    // 但这里只有一个appConfig.class
    Set candidates = new LinkedHashSet(configCandidates);
    // alreadyParsed用于存放是否已经处理过
    Set alreadyParsed = new HashSet(configCandidates.size());
    do {
        // 解析,重要!!!看第二小点
        parser.parse(candidates);
        parser.validate();

        // parser.getConfigurationClasses()方法拿到所有扫描到和Import导入等所有方式导入的类信息
        Set 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());
        }

       /**
		* 这里值得注意的是扫描出来的bean当中可能包含了特殊类
		* 比如ImportBeanDefinitionRegistrar那么也在这个方法里面处理
		* 但是并不是包含在configClasses当中
		* configClasses当中主要包含的是importSelector
		* 因为ImportBeanDefinitionRegistrar在扫描出来的时候已经被添加到一个list当中去了
		* bd 到 map 除去普通
		*/
        // 此处会把Import方式导入的Bean放到bdMap中!!!!
        // import导入的ImportBeanDefinitionRegistrar会在这里调用其registerBeanDefinitions()方法
        // ImportBeanDefinitionRegistrar的实例化在processImports()方法时已经通过BeanUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class);进行了创建
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);

        candidates.clear();
        // 由于我们这里进行了扫描,把扫描出来的BeanDefinition注册给了factory
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set oldCandidateNames = new HashSet(Arrays.asList(candidateNames));
            Set 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();
    }
}
2. parser.parse()

ConfigurationClassParser类中的parse()方法:

public void parse(Set configCandidates) {
    
    this.deferredImportSelectors = new LinkedList();

    //根据BeanDefinition 的类型 做不同的处理,一般都会调用ConfigurationClassParser#parse 进行解析
    // 此处初始传进来就是一个配置类appConfig.class
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                // 解析注解对象,并且把解析出来的BeanDefinition放到bdMap,但是这里的BeanDefinition指的是普通的
                // 何为普通呢?就是被扫描到的类会直接转化为bd,然后放到bdMap中
                // 何谓不普通的呢?比如@Bean和各种beanFactoryPostProcessor得到的bean,不在这里put
                // 但是是这里解析,只是不put而已
                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) {
			// 抛异常略
        }
    }

    // 处理延迟加载的importSelect?为什么要延迟加载,估计就是为了延迟吧
    processDeferredImportSelectors();
}

protected final void parse(AnnotationMetadata metadata, String beanName) {
    
    // 根据注解信息和beanName创建一个ConfigurationClass,下面第三小点
    // 此方法或被多处递归调用!!!比较难理解,可以debug调试尝试理解
    processConfigurationClass(new ConfigurationClass(metadata, beanName));
}
3. processConfigurationClass()(重点!!!)
protected void processConfigurationClass(ConfigurationClass configClass)  {
    // 根据注解信息判断是不是跳过解析
    if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
        return;
    }

    // 处理Imported 的情况,就是当前这个注解类有没有被别的类import
    ConfigurationClass existingClass = this.configurationClasses.get(configClass);
    if (existingClass != null) {
        if (configClass.isImported()) {
            if (existingClass.isImported()) {
                existingClass.mergeImportedBy(configClass);
            }
            return;
        } else {
            this.configurationClasses.remove(configClass);
            this.knownSuperclasses.values().removeIf(configClass::equals);
        }
    }

    // 递归地处理配置类及其超类层次结构。
    SourceClass sourceClass = asSourceClass(configClass);
    do {
        // 处理配置类,下面第四小点
        sourceClass = doProcessConfigurationClass(configClass, sourceClass);
    }
    while (sourceClass != null);

    this.configurationClasses.put(configClass, configClass);
}
4. doProcessConfigurationClass()
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass){

    // 首先递归地处理任何成员(嵌套)类
    processMemberClasses(configClass, sourceClass);

    // 处理 @PropertySource注解
    for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), PropertySources.class,
        org.springframework.context.annotation.PropertySource.class)) {
        if (this.environment instanceof ConfigurableEnvironment) {
            processPropertySource(propertySource);
        }
    }

    // 处理@ComponentScan注解
    // 此处或扫描到@ComponentScan注解包下面的所有加了@Component、@Service等注解的类
    // 注意的是,每扫描到一个符合条件的类,都要进行递归扫描,重新调用doProcessConfigurationClass()方法
    // 扫描到的类,随机转化为bd,然后放入到bdMap中
    Set componentScans = AnnotationConfigUtils.attributesForRepeatable(
        sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
    if (!componentScans.isEmpty() && !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
        for (AnnotationAttributes componentScan : componentScans) {
            // 扫描解析在这里
            // 扫描普通类,componentScan=com.scorpios
            // 这里扫描出来所有@Component,并且把扫描的出来的普通bean放到bdMap当中
            // 方法详解见第5小节
            Set scannedBeanDefinitions = this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());

            // 检查扫描的定义集是否有任何进一步的配置类,并在需要时进行递归解析,
            // 检查扫描出来的类当中是否还有configuration
            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());
                }
            }
        }
    }

    
	// 上面的代码就是扫描普通类----@Component,并且将扫描到的class转化为bd,并放到了bdMap当中

    /**
    *  下面这个方法是处理@Import  imports导入类的3种情况
    *  1.ImportSelector
    *  2.普通类
    *  3.ImportBeanDefinitionRegistrar
    * 这里处理的import是需要判断我们的配置类有@Import注解
    * 如果有这把@Import当中的值拿出来,是一个类,
    * 比如@Import(xxxxx.class),那么这里便把xxxxx传进去进行解析
    * 在解析的过程中如果发觉是一个importSelector那么就回调selector()的方法
    * 返回一个字符串(类名),通过这个字符串得到一个类
    * 继而在递归调用本方法来处理这个类
    * 判断一组类是不是imports(3种import)
    * 此处import导入的类并不会立刻转化为bd放入到bdMap中
    */
    processImports(configClass, sourceClass, getImports(sourceClass), true);

    // 处理 @ImportResource注解
    AnnotationAttributes importResource = AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
    if (importResource != null) {
        String[] resources = importResource.getStringArray("locations");
        Class readerClass = importResource.getClass("reader");
        for (String resource : resources) {
            String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
            configClass.addImportedResource(resolvedResource, readerClass);
        }
    }

   	// 处理单个的@Bean方法
    Set beanMethods = retrieveBeanMethodMetadata(sourceClass);
    for (MethodMetadata methodMetadata : beanMethods) {
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
    }

    // 处理接口上的默认方法
    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;
}
5. parse()

ComponentScanAnnotationParser中的parse()方法

public Set parse(AnnotationAttributes componentScan, final String declaringClass) {
    // spring自己new的一个ClassPathBeanDefinitionScanner进行扫描!!!
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(this.registry,
                         componentScan.getBoolean("useDefaultFilters"), this.environment, this.resourceLoader);

    Class generatorClass = componentScan.getClass("nameGenerator");
    boolean useInheritedGenerator = (BeanNameGenerator.class == generatorClass);
    // 设置扫描器的BeanName生成器
    scanner.setBeanNameGenerator(useInheritedGenerator ?
    							 this.beanNameGenerator : BeanUtils.instantiateClass(generatorClass));

    // 设置componentScan的代理模式
    ScopedProxyMode scopedProxyMode = componentScan.getEnum("scopedProxy");
    if (scopedProxyMode != ScopedProxyMode.DEFAULT) {
        scanner.setScopedProxyMode(scopedProxyMode);
    } else {
        Class resolverClass = componentScan.getClass("scopeResolver");
        scanner.setScopeMetadataResolver(BeanUtils.instantiateClass(resolverClass));
    }

    // 设置扫描器的资源模式
    scanner.setResourcePattern(componentScan.getString("resourcePattern"));

    // 看看componentScan注解是否设置了includeFilters属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("includeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addIncludeFilter(typeFilter);
        }
    }

    // 看看componentScan注解是否设置了excludeFilters属性
    for (AnnotationAttributes filter : componentScan.getAnnotationArray("excludeFilters")) {
        for (TypeFilter typeFilter : typeFiltersFor(filter)) {
            scanner.addExcludeFilter(typeFilter);
        }
    }

    // 	看看componentScan注解是否设置了lazyInit属性
    boolean lazyInit = componentScan.getBoolean("lazyInit");
    if (lazyInit) {
        scanner.getBeanDefinitionDefaults().setLazyInit(true);
    }

    // 此集合放的是扫描的路径
    Set basePackages = new LinkedHashSet();
    // 获取componentScan注解的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);
        }
    });
    // 开始扫描,方法见第6小节
    return scanner.doScan(StringUtils.toStringArray(basePackages));
}
6. doScan()
// 传入要扫描的包
protected Set doScan(String... basePackages) {
    Set beanDefinitions = new LinkedHashSet();
    for (String basePackage : basePackages) {
        // 扫描basePackage路径下的java文件,符合条件的并把它转成BeanDefinition类型
        Set candidates = findCandidateComponents(basePackage);
        // 循环遍历扫描到的Bean
        for (BeanDefinition candidate : candidates) {
            // 解析scope属性
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            if (candidate instanceof AbstractBeanDefinition) {
                // 如果这个类是AbstractBeanDefinition的子类
                // 则为它设置默认值,比如lazy,init destory
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            if (candidate instanceof AnnotatedBeanDefinition) {
                // 检查并且处理常用的注解
                // 这里的处理主要是指把常用注解的值设置到AnnotatedBeanDefinition当中
                // 当前前提是这个类必须是AnnotatedBeanDefinition类型的,说白了就是加了注解的类 
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {

                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                definitionHolder =
                    AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 创建Bean,并放入到beanDefinitionMap中,和beanDefinitionNames中,但singletonObjects中还没有
                // 加入到bdMap当中
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}

到此处已经完成了扫描工作,比如被@Component@Service等注解修饰的类,已经从class转换层bd,并放入到bdMap中,但这些Bean并没有实例化。

7. 小结

processConfigBeanDefinitions()方法执行开始说起:

  • 首先把配置类appConfig.class类转化后的的BeanDefinition标记为Full还是Lite
  • 然后第一次进入到parser.parse()方法时,参数只有一个配置类appConfig.class
  • 接着调用parser.parse(appConfig.class)开始扫描,此处是个循环
  • 接着调用doProcessConfigurationClass()方法,被递归调用
    • 在这个方法中,先处理@PropertySource注解
    • 接着处理@ComponentScan注解,把扫描到的类符合条件的放入到集合中,遍历这个结合,再次调用parse()扫描方法。此处扫描出来的类,会被转化为BeanDefinition,然后放入到bdMap
    • 接着处理@Import注解,分三种情况,分别是:ImportSelectorImportBeanDefinitionRegistrar、普通导入类。此处会递归调用processConfigurationClass()方法来确定被导入的类是否又需要解析。注意,此处导入符合条件的类,并不会立即转化为BeanDefinition,而是在第一小节processConfigBeanDefinitions()方法中才会被转化,并放入到bdMap
    • 接着处理@ImportResource注解
    • 接着处理处理单个的@Bean方法
    • ……

在doProcessConfigurationClass()方法中扫描出来的类已经转化为BeanDefinition,会再次循环检查否有进一步的配置类,并会返回的BeanDefinition进行递归调用,再解析!!!

二、postProcessBeanFactory()

此方法为接口BeanFactoryPostProcessor中的方法。

public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    this.factoriesPostProcessed.add(factoryId);
    // registriesPostProcessed中已经包含了factoryId
    if (!this.registriesPostProcessed.contains(factoryId)) {
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }
	// 根据方法名,顾名思义,增强配置类
    enhanceConfigurationClasses(beanFactory);
    // 向Spring容器中添加一个ImportAwareBeanPostProcessor后置处理器
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
1. enhanceConfigurationClasses()
// 此方法传入的是BeanFactory工厂
public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    
    // 此Map是存放具有Full属性的BeanDefinition
    Map configBeanDefs = new LinkedHashMap();
    
    // 遍历BeanFactory工厂中的BeanDefinitionNames
    for (String beanName : beanFactory.getBeanDefinitionNames()) {
        // 根据beanName从bdMap中拿到对应的BeanDefinition
        BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);
        // 判断BeanDefinition是否是Full类型
        if (ConfigurationClassUtils.isFullConfigurationClass(beanDef)) {
			// 抛异常代码略
            configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);
        }
    }
    
    if (configBeanDefs.isEmpty()) {
        // nothing to enhance -> return immediately
        return;
    }

    // 创建一个配置类增强器
    ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();
    
    // 循环存放属性为Full的BeanDefinition
    for (Map.Entry entry : configBeanDefs.entrySet()) {
        
        AbstractBeanDefinition beanDef = entry.getValue();
        // If a @Configuration class gets proxied, always proxy the target class
        beanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);
        try {
            // Set enhanced subclass of the user-specified bean class
            Class configClass = beanDef.resolveBeanClass(this.beanClassLoader);
            if (configClass != null) {
                // 完成对全注解类的cglib代理
                Class enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);
                if (configClass != enhancedClass) {
                    beanDef.setBeanClass(enhancedClass);
                }
            }
        } catch (Throwable ex) {
            // 抛异常代码略
        }
    }
}
2. enhance()
public Class enhance(Class configClass, @Nullable ClassLoader classLoader) {
   // 判断是否被代理过
   if (EnhancedConfiguration.class.isAssignableFrom(configClass)) {
      return configClass;
   }
    
   // 没有被代理cglib代理
   Class enhancedClass = createClass(newEnhancer(configClass, classLoader));
   return enhancedClass;
}
3. newEnhancer()
// Creates a new CGLIB {@link Enhancer} instance.
private Enhancer newEnhancer(Class configSuperClass, @Nullable ClassLoader classLoader) {
   Enhancer enhancer = new Enhancer();
   // 增强父类,地球人都知道cglib是基于继承来的
   enhancer.setSuperclass(configSuperClass);
   // 增强接口,为什么要增强接口? 便于判断,表示一个类以及被增强了
   enhancer.setInterfaces(new Class[] {EnhancedConfiguration.class});
   // 不继承Factory接口
   enhancer.setUseFactory(false);
   enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
   // BeanFactoryAwareGeneratorStrategy是一个生成策略
   // 主要为生成的CGLIB类中添加成员变量$$beanFactory
   // 同时基于接口EnhancedConfiguration的父接口BeanFactoryAware中的setBeanFactory方法,
   // 设置此变量的值为当前Context中的beanFactory,这样一来我们这个cglib代理的对象就有了beanFactory    	
   // 有了factory就能获得对象,而不用去通过方法获得对象了,因为通过方法获得对象不能控制器过程
   // 该BeanFactory的作用是在this调用时拦截该调用,并直接在beanFactory中获得目标bean
   enhancer.setStrategy(new BeanFactoryAwareGeneratorStrategy(classLoader));
   // 过滤方法,不能每次都去new
   enhancer.setCallbackFilter(CALLBACK_FILTER);
   enhancer.setCallbackTypes(CALLBACK_FILTER.getCallbackTypes());
   return enhancer;
}
4. createClass()
private Class createClass(Enhancer enhancer) {
   Class subclass = enhancer.createClass();
   Enhancer.registerStaticCallbacks(subclass, CALLBACKS);
   return subclass;
}
5.小结

此方法就是为全注解类生成的cglib代理,至于代理类的生成,是通过使用Enhancer增强器。这个知识点可以自行查看一下。

那何为全注解类呢?

就是当前类有没有被@Configuration注解修饰

postProcessBeanFactory()方法还往容器中添加了一个BeanPostProcessorImportAwareBeanPostProcessor

以上就是对ConfigurationClassPostProcessor的功能解析,这个类非常重要,也很难理解。

关注
打赏
1657848381
查看更多评论
立即登录/注册

微信扫码登录

0.1574s