上一篇我們将AnnotationConfigApplicationContext構造函數的整體流程梳理一遍,今天我們來詳細聊聊Spring是如何掃描得到所有需要被管理的Bean資訊的,這裡用一個專業名詞來表示Bean資訊叫BeanDefinition,後面我們都簡稱BD,我們後面會有專門章節來說明BD的類繼承關系。
上一篇我們講到invokeBeanFactoryPostProcessors是完成掃描的核心方法,那麼我們進入該方法來看看:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
關鍵代碼就是PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()),在進一入invokeBeanFactoryPostProcessors方法:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 關鍵點一、這個beanFactoryPostProcessors集合一般情況下都是空的,除非我們手動調用容器的addBeanFactoryPostProcessor方法
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}else {
regularPostProcessors.add(postProcessor);
}
}
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//關鍵點二、執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//關鍵點三
String[] postProcessorNames =beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}else {
nonOrderedPostProcessorNames.add(ppName);
}
}
//關鍵點四、執行BeanFactoryPostProcessor的postProcessBeanFactory方法
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
代碼有點多,但是歸納起來就做了兩件事:第一執行BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,也就是對BeanDefinition進行處理;第二執行BeanFactoryPostProcessor的postProcessBeanFactory方法,執行BeanFactory的後置處理器邏輯。下面我們就來詳細說說。
- 關鍵點一
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}else {
regularPostProcessors.add(postProcessor);
}
}
beanFactoryPostProcessors一般情況下都是空的,除非我們手動調用容器的addBeanFactoryPostProcessor方法,這裡Spring提供了一個擴充點,一般情況下不會使用。
- 關鍵點二
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
//
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
首先:
看currentRegistryProcessors這個對象,他的主要作用就是記錄目前将要執行的BeanDefinitionRegistryPostProcessor執行個體,首先擷取到所有的BeanDefinitionRegistryPostProcessor,然後将PriorityOrdered類型的BeanDefinitionRegistryPostProcessor對象添加到currentRegistryProcessors集合中。注意這裡擷取到的BeanDefinitionRegistryPostProcessor類型對象隻有一個ConfigurationClassPostProcessor,那這個類是什麼時候添加到BeanFactory裡面去的呢?咱們還記得上一篇構造函數裡面建立了一個reader對象嗎?代碼如下:
this.reader = new AnnotatedBeanDefinitionReader(this);
AnnotatedBeanDefinitionReader的構造函數中調用了如下代碼:
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
這段代碼中建立了五個類型的對象,并将這五個類型對象添加到了BeanFactory中:
1.ConfigurationClassPostProcessor
2.AutowiredAnnotationBeanPostProcessor
3.CommonAnnotationBeanPostProcessor
4.EventListenerMethodProcessor
5.DefaultEventListenerFactory
而ConfigurationClassPostProcessor又實作了BeanDefinitionRegistryPostProcessor和PriorityOrdered:
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {...}
然後執行如下代碼:
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
這裡開始執行上述的ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法,這個方法就是掃描得到所有的BeanDefinition,由于這裡比較複雜,後續我們專門文章來分析,這裡先跳過,大家隻要知道它的作用即可。
其次:
依次類推,将執行Ordered.class類型的BeanDefinitionRegistryPostProcessor執行個體對象。
最後
需要執行普通的BeanDefinitionRegistryPostProcessor執行個體對象:
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
但是很奇怪,這裡為啥要加個while循環?Spring有病吧?當然沒病,人家Spring考慮的周全。這裡表示執行上面沒有執行的BeanDefinitionRegistryPostProcessor,而且你在執行過程中,可能會産生新的BeanDefinitionRegistryPostProcessor對象,是以才用個while循環,直到執行完所有的BeanDefinitionRegistryPostProcessor才結束;
執行完後,再執行BeanDefinitionRegistryPostProcessor實作類的postProcessBeanFactory方法(因為BeanDefinitionRegistryPostProcessor也是BeanFactoryPostProcessor的實作),這裡就會執行ConfigurationClassPostProcessor的postProcessBeanFactory方法:
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
ConfigurationClassPostProcessor的postProcessBeanFactory方法有點特别:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
enhanceConfigurationClasses這個方法用于判斷是否需要對配置類生成代理對象?什麼是配置類?增加了@Configuration注解的類是配置了,它有什麼特點呢?凡是在配置類中被@Bean聲明的對象都需要代理,是以這裡需要對@Configuration類型的對象進行特殊處理;
然後添加ImportAwareBeanPostProcessor後置處理器,這個是對@import注解進行處理的Bean的後置處理器,後續我們再講。
- 關鍵點三
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}else {
nonOrderedPostProcessorNames.add(ppName);
}
}
這裡看代碼很簡單,就是把所有的BeanFactoryPostProcessor對象分别放到三個集合裡面去,然後按優先級先後執行priorityOrderedPostProcessors、orderedPostProcessorNames、nonOrderedPostProcessorNames中的BeanFactoryPostProcessor對象,但是為什麼不像上面的BeanDefinitionRegistryPostProcessor一樣處理,而是直接分到三個集合裡面呢?這個也很簡單,因為執行BeanFactoryPostProcessor方法不會産生新的BeanFactoryPostProcessor對象,是以為了提升效率,直接分組到不同的集合即可。
- 關鍵點四
這裡就開始執行BeanFactoryPostProcessor的postProcessBeanFactory方法了,先執行priorityOrderedPostProcessors集合中的,其次執行orderedPostProcessorNames集合中的,最後執行nonOrderedPostProcessorNames集合中的。