spring原始碼分析——BeanPostProcessor介面

warrior1234發表於2020-06-18

 

  BeanPostProcessor是處理bean的後置介面,beanDefinitionMaps中的BeanDefinition例項化完成後,完成populateBean,屬性設定,完成

初始化後,這個介面支援對bean做自定義的操作。

一:BeanPostProcessor的使用

定義一個測試用的model物件,name屬性預設為hello

public class BeanDemo {

	private String name = "hello";

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		final StringBuffer sb = new StringBuffer("BeanDemo{");
		sb.append("name='").append(name).append('\'');
		sb.append('}');
		return sb.toString();
	}
}

  

自定義一個MyBeanPostProcessor類,實現BeanPostProcessor介面

@Service
public class MyBeanPostProcessor implements BeanPostProcessor {

	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return null;
	}

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if(beanName.equals("beanDemo")){
			BeanDemo beanDemo = (BeanDemo)bean;
			beanDemo.setName("kitty");
			return beanDemo;
		}
		return bean;
	}
}

  

 

 

從執行結果看,spring中維護的beanName為beanDemo的物件,name屬性為ketty

 

 

二:看看原始碼怎麼實現的

1:例項化並且註冊到beanPostProcessors集合中

 

 

 

 

主要的例項化邏輯在這個介面,這個介面的作用就是把所有實現BeanPostProcessor介面的類例項化,然後註冊到 beanPostProcessors這個快取中

 

 

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		// 獲取所有實現介面BeanPostProcessor的beanName
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		/**
		 * 把實現PriorityOrdered 和 Ordered 和 其他的處理器分開
		 */
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		/**
		 * 1:遍歷集合postProcessorNames
		 * 2:判斷型別,如果是PriorityOrdered,則例項化物件放入priorityOrderedPostProcessors集合,
		 * Ordered 則放入orderedPostProcessorNames集合,其他的放入nonOrderedPostProcessorNames集合
 		 */
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		// 首先對priorityOrderedPostProcessors集合中例項物件排序,然後註冊,放入beanFactory中快取下來
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		// 然後再例項化實現Ordered介面的物件,完成註冊
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		// 最後例項化什麼都沒有實現的,完成例項化並註冊
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		// 最後再次註冊內部postProcessor
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

  

 

 

定義四類容器,高優先順序有序、有序、無序、內部

 

 分類放入四種容器:

 

 

註冊BeanPostProcessor,將實現BeanPostProcessor介面的物件放入beanPostProcessors快取中

 

 

 

 

 

 

註冊完PriorityOrdered的實現類後,再處理Ordered的實現類

 

 

註冊什麼都沒有實現的BeanPostProcessor介面實現類,

 

 

最後註冊內部的BeanPostProcessor物件

 

 到這裡BeanPostProcessor的例項化以及註冊工作完成,在beanFactory的beanPostProcessors集合中已經快取了所有的beanPostProcessor的物件

 

2:BeanPostProcessor的使用

因為這個介面是bean的後置介面,所以需要bean建立並初始化完成,才可以發揮作用,上一步的快取只是埋好點,以備使用,因為bean的例項化流程我們

還沒有分析,這裡直接看一下怎麼使用的

 

 

我們看一下init方法後的攔截,因為這個時候已經init完成,可以在後置介面中對bean做一下修改的操作

 

 

呼叫到我們自定義的MyBeanPostProcessor實現類:

 

 

把這個beanDemo物件屬性修改一下,修改完,再返回,將這個物件快取到spring的一級快取中。

 

 

總結:

  BeanPostProcessor介面主要是對bean物件做一些自定義的操作,修改bean物件的資訊,aop代理也是通過這種方式實現的,

在refresh的registryBeanPostProcessor方法中例項化BeanPostProcessor物件,並且註冊到beanFactory容器的beanPostProcessors的快取中,

然後在後續的操作中攔截使用。

 

相關文章