知識回顧
Bean
的建立過程會經歷getBean
,doGetBean
,createBean
,doCreateBean
,然後Bean
的建立又會經歷例項化,屬性填充,初始化。
在例項化createInstance
時大致可以分為三種方式進行例項化:
- 使用
Supplier
進行例項化,通過BeanFactoryPostProcessor
對BeanDefinition
進行修改,增加一個Supplier
屬性,放置一個lambda
表示式用於建立物件 - 使用
factory-method
進行例項化- 使用例項工廠例項化
- 使用靜態工廠例項化
- 使用構造器反射進行例項化
- 使用
SmartInstantiationAwareBeanPostProcessor
解析構造器,然後反射例項化 - 使用無參構造器進行例項化
- 使用
在屬性填充populateBean
時大致可以分為4個步驟:
- 呼叫
InstantiationAwareBeanPostProcessor
介面的after
方法修改Bean
的資訊 - 自動裝配,將解析的屬性和屬性值放入到
pvs
變數中- 按
autowireByType
自動裝配 - 按
autowireByName
自動裝配
- 按
- 執行通過
CommonAnnotationBeanPostProcessor
和AtowiredAnnotationBeanPostProcessor
解析的註解,然後注入到欄位上 - 對屬性的值進行解析,解析
pvs
, 會涉及到引數轉換,spel
表示式解析,引用型別,String
型別,List
型別,Map
型別,Set
型別,Properties
型別的解析,屬性編輯器的解析等。
接下來解讀初始化階段
bean的初始化
bean
的初始化initializeBean
方法,直接上原始碼:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 執行Aware 方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
// 執行 BeanPostProcessor before 介面
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
// 執行 init-method 方法
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()) {
// 執行BeanPostProcessor after 方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
原始碼邏輯也很簡單,大概就分成了4步:
- 執行
Aware
介面的方法invokeAwareMethods
- 執行
BeanPostProcessor#postProcessBeforeInitialization
- 執行初始化方法
- 執行
BeanPostProcessor#postProcessAfterInitialization
執行Aware介面的方法
點進去:
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
// 執行BeanNameAware
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
// 執行BeanClassLoaderAware
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
// 執行BeanFactoryAware
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
這裡只執行了3個介面的方法,BeanNameAware
,BeanClassLoaderAwre
,BeanFactoryAware
,在Spring
容器中不止這些Aware
介面,這裡為什麼只執行了三個Aware介面?
在Spring
容器BeanFactory
構造時,對這三個介面進行了忽略:
public AbstractAutowireCapableBeanFactory() {
super();
ignoreDependencyInterface(BeanNameAware.class);
ignoreDependencyInterface(BeanFactoryAware.class);
ignoreDependencyInterface(BeanClassLoaderAware.class);
}
所以這裡只執行了這三個Aware
介面,這裡忽略,實際上就是不然這些屬性通過自動裝配設定屬性值,而是通過Spring
自己的回撥進行設定值。
另外我們在開始的準備BeanFactory
的時候又進行了忽略Aware
介面:
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
這6個介面在哪裡執行的呢?在BeanFactory
準備階段註冊了一個BeanPostProcessor
的實現叫ApplicationContextAwareProcessor
類,這個類的before
方法中就進行了呼叫:
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
return bean;
}
AccessControlContext acc = null;
if (System.getSecurityManager() != null) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if (acc != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareInterfaces(bean);
return null;
}, acc);
}
else {
// 執行Aware介面
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
為什麼要分開處理呢?
個人認為主要是做了個區分而已,前面三個介面輸入BeanFactory
範疇,而這6個介面屬於ApplicationContext
範疇,只是進行了歸類處理而已。
執行BPP的Before方法
程式碼比較簡單,就是迴圈的執行了BPP
的before
介面,這裡在執行的時候,實現上也執行了在Bean
進行merge
的時候解析的@PostConstruct
註解。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
// 執行初始化方法
metadata.invokeInitMethods(bean, beanName);
}
catch (InvocationTargetException ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
}
return bean;
}
這個方法的實現類為InitDestroyAnnotationBeanPostProcessor
執行初始化方法
執行初始化方法的時候,會分為兩步,一個是執行InitializingBean
的afterPropertiesSet
方法,另一個是執行自定義的init-method
方法
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 判斷當前Bean是否是實現了InitializingBean
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
// 執行
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 執行自定義的初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
執行BPP的after介面
BPP的after主要是用來實現AOP的,所以這裡簡單介紹下,迴圈執行after方法的呼叫。
原始碼:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
原始碼比較簡單,就迴圈執行了方法的呼叫。
初始化就解讀完了,Spring
的Bean
的建立也基本講完,最終建立出來的Bean
物件就會放入到一級快取singletonObjects
中。