ConfigurationClassPostProcessor
在前面一个章节,笔者和大家介绍了在构造一个应用上下文时,spring会执行到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(...)方法,我们已经清楚这个方法的整个流程,也知道在这个方法里会调用spring内置的BeanDefinitionRegistryPostProcessor实现类——ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry(...)方法,在这个方法中会完成BeanDefinition的扫描。本章我们就要来学习ConfigurationClassPostProcessor这个类,看看这个类实现的processConfigBeanDefinitions(...)是如何完成扫描BeanDefinition。
在这个方法中会在<1>处获取传入的BeanDefinitionRegistry对象的唯一哈希码(identityHashCode)registryId,判断这个哈希码是否在registriesPostProcessed集合中,如果存在则表示当前的配置类后置处理器(ConfigurationClassPostProcessor)曾经处理过传入的BeanDefinitionRegistry对象,会进入<2>处的分支抛出异常。如果配置类后置处理器从未处理过传入的BeanDefinitionRegistry对象,在<3>处会把BeanDefinitionRegistry对象的哈希码加入到registriesPostProcessed集合。
代码<1>~<3>只是做了幂等性校验,避免配置类后置处理器重复处理同一个BeanDefinitionRegistry对象,这里我们也可以看出扫描BeanDefinition的工作一定不是在<1>~<3>处的代码完成的,那就只能是在21行执行processConfigBeanDefinitions(registry)时完成的。同时我们也注意到在<2>~<3>之间会把哈希码加到factoriesPostProcessed集合,之所以有这一步操作是为了后续执行配置类后置处理器时如果发现传入的BeanFactory对象的哈希码在factoriesPostProcessed集合中,可以将BeanFactory对象强制转换成BeanDefinitionRegistry类型做一些额外的工作。
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware { …… private final Set<Integer> registriesPostProcessed = new HashSet<>(); private final Set<Integer> factoriesPostProcessed = new HashSet<>(); …… @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) { int registryId = System.identityHashCode(registry);//<1> if (this.registriesPostProcessed.contains(registryId)) {//<2> throw new IllegalStateException( "postProcessBeanDefinitionRegistry already called on this post-processor against " + registry); } if (this.factoriesPostProcessed.contains(registryId)) { throw new IllegalStateException( "postProcessBeanFactory already called on this post-processor against " + registry); } this.registriesPostProcessed.add(registryId);//<3> processConfigBeanDefinitions(registry); } …… }