Spring原始碼解析—第四篇IOC之BeanPostProcessor
1、BeanPostProcessor簡介
BeanPostProcessor是Spring IOC容器給我們提供的一個擴充套件介面。介面宣告如下:
public interface BeanPostProcessor { //bean初始化方法呼叫前被呼叫 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; //bean初始化方法呼叫後被呼叫 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException; }
BeanPostProcessor介面有兩個回撥方法。當一個BeanPostProcessor的實現類註冊到Spring IOC容器後,對於該Spring IOC容器所建立的每個bean例項在初始化方法呼叫前,將會呼叫BeanPostProcessor中的postProcessBeforeInitialization方法,而在bean例項初始化方法呼叫完成後,則會呼叫BeanPostProcessor中的postProcessAfterInitialization方法。
2、例項
修改上面的例項,增加ChangeUserBeanPostProcessor
2.1、ChangeUserBeanPostProcessor類
package com.vesus.spring.processor; import com.vesus.spring.model.User; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; /** * @Description: * @Author: vesus * @CreateDate: 2018/6/3 下午3:51 * @Version: 1.0 */ public class ChangeUserBeanPostProcessor implements BeanPostProcessor { //初始化之前處理 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof User){ User user = (User) bean; user.setName("我是小明!"); } return bean; } //初始化之後處理 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } }
2.2、配置檔案增加
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.vesus.spring.model.User" />
<bean id="changeUser" class="com.vesus.spring.processor.ChangeUserBeanPostProcessor"/>
</beans>
2.3、測試類
public class Test {
public static void main(String[] args) {
BeanFactory beanFactory = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) beanFactory.getBean("user") ;
System.err.println(user.getName()+":"+user.getDesc());
}
}
2.4、測試結果
我是小明!:使用者類
3、原始碼分析
3.1、入口方法refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
.....
try {
......
//開始註冊BeanPostProcessor來攔截其他的bean的初始化過程
registerBeanPostProcessors(beanFactory);
.....
//初始化單例
finishBeanFactoryInitialization(beanFactory);
.....
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
從入口方法中可以看到,BeanPostProcessor 的註冊方法registerBeanPostProcessors,下面分析registerBeanPostProcessors 的註冊過程
3.2、registerBeanPostProcessors註冊方法解析
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
// 獲取所有BeanPostProcessor型別的bean名稱
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// 註冊BeanPostProcessorChecker,它可以列印BeanPostProcessor例項化過程中建立bean的日誌資訊
// 計算已註冊的bean + 1 +上面獲取到的bean的數量,1是即將建立的BeanPostProcessorChecker
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// 按照優先的、內部的、排序的、無排序的進行分組排序,
// 其中優先bean多了MergedBeanDefinitionPostProcessor型別(merged bean definition)
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
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);
}
}
//註冊優先Order的後處理器
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
//註冊實現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);
// 註冊未排序的處理器
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);
// 註冊內部的處理器
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
// 註冊BeanPostProcessor:ApplicationListenerDetector,這個是AbstractApplicationContext的內部類
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
3.3、呼叫方法finishBeanFactoryInitialization解析
Bean 的例項化程式碼,是從 finishBeanFactoryInitialization 方法開始的
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
beanFactory.setTempClassLoader(null);
beanFactory.freezeConfiguration();
//進行類的初始化
beanFactory.preInstantiateSingletons();
}
從上面程式碼中可以發現 Bean 的例項化是呼叫的是preInstantiateSingletons方法,接續往下找我們會找到AbstractAutowireCapableBeanFactory的doCreateBean方法。
3.4、doCreateBean方法解析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//初始化一個BeanWrapper
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//建立bean例項
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
.....
//初始化bean例項
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
在該方法中,呼叫createBeanInstance方法,建立bean例項物件,之後再呼叫方法initializeBean,進行相關初始化工作。
3.5、initializeBean方法解析
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//在初始化之前處理執行處理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//開始執行初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//在初始化之後處理執行處理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
至此,BeanPostProcessor的原始碼分析完成。