一、refresh 方法之 finishBeanFactoryInitialization
這個方法非常重要,執行流程也非常複雜。
上面我們做了那麼多詳細的介紹,僅僅隻是為這一步做鋪墊,該方法就是将上面注冊進BeanFactory中的所有單執行個體Bean定義進行執行個體化的功能。
源碼入口
finishBeanFactoryInitialization(beanFactory);
進入
org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
// 最先初始化名字為 conversionService的類,conversionService類 它用來将前端傳過來的參數和後端的 controller 方法上的參數進行綁定的時候用
// 尤其是用于非基礎類型的轉換
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
// 初始化在getBean()方法中實作
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
// 如果之前沒有注冊過任何 bean 後處理器(例如 PropertyPlaceholderConfigurer bean),則注冊一個預設的嵌入值解析器:此時,主要用于解析注釋屬性值。
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
// 先初始化 LoadTimeWeaverAware 類型的 Bean aop相關注
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
// 停止使用臨時的ClassLoader進行類型比對。
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
// freeze的單詞意思是當機,這個時候已經開始預初始化, bean 定義解析、加載、注冊先停止
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
// 執行個體化單例 bean
beanFactory.preInstantiateSingletons();
}
這裡沒做啥事情,唯一需要注意的是就是向 beanFactory 中加了個類型轉換器。
那我們接着進入 preInstantiateSingletons 方法:
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// this.beanDefinitionNames 儲存了所有的 beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
// 下面這個循環,觸發所有的非懶加載的 singleton beans 的初始化操作
for (String beanName : beanNames) {
// 擷取 bd 資訊, 因為可能 定義了 parentBeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 非抽象、非懶加載的 singletons。如果配置了 'abstract = true',那是不需要初始化的
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 處理 FactoryBean (負責初始化工廠的bean)
if (isFactoryBean(beanName)) {
// FactoryBean 需要添加字首 & ,通過 getBean(&beanName) 擷取的是 FactoryBean 本身
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
// 判斷是否需要初始化且目前 FactoryBean 是否是 SmartFactoryBean 的實作
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
((SmartFactoryBean<?>) factory).isEagerInit(),
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
// 需要初始化
if (isEagerInit) {
getBean(beanName);
}
}
else {
// 對于普通的 Bean,隻要調用 getBean(beanName) 這個方法就可以進行初始化了
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
// 到這裡說明所有的非懶加載的 singleton beans 已經完成了初始化
// 如果我們定義的 bean 是實作了 SmartInitializingSingleton 接口的,那麼在這裡得到回調
// 如果你想在單例bean初始化後做一些事 那就實作該接口
for (String beanName : beanNames) {
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
smartSingleton.afterSingletonsInstantiated();
return null;
}, getAccessControlContext());
}
else {
smartSingleton.afterSingletonsInstantiated();
}
}
}
}
這個方法主要功能分為兩步:
- 擷取所有 BeanName 進行周遊執行個體化出所有的單執行個體Bean
- 周遊 BeanName 判斷 Bean 是否實作 SmartInitializingSingleton ,是則執行對應的 afterSingletonsInstantiated 方法。
第二步是沒有什麼好說的,就是方法的調用,我們重點關注第一步。
第一步先擷取所有的 BeanName 集合在 this.beanDefinitionNames 屬性中,然後挨個周遊,判斷是否為非抽象懶加載的 Bean,如果是則還會判斷是普通的 Bean 初始化還是 FactoryBean 初始話,但兩者最終走得都是 getBean 方法,是以下面我們就來分析分析。
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
繼續進入
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 擷取一個 “正統的” beanName,處理兩種情況,一個是前面說的 FactoryBean(前面帶 ‘&’),
// 一個是别名問題,因為這個方法是 getBean,擷取 Bean 用的,你要是傳一個别名進來,是完全可以的
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 先從單例緩存池中擷取 Bean ,檢查下是不是已經建立過了
Object sharedInstance = getSingleton(beanName);
// 這裡說下 args ,雖然看上去一點不重要。前面我們一路進來的時候都是 getBean(beanName),
// 是以 args 傳參其實是 null 的,但是如果 args 不為空的時候,那麼意味着調用方不是希望擷取 Bean,而是建立 Bean
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 下面這個方法:如果是普通 Bean 的話,直接傳回 sharedInstance,
// 如果是 FactoryBean 的話,傳回它建立的那個執行個體對象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
// 建立過了此 beanName 的 prototype 類型的 bean,那麼抛異常,
// 循環依賴隻能解決單例模式,原型模式不能解決
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// Check if bean definition exists in this factory.
// 檢查一下這個 BeanDefinition 在容器中是否存在
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
// 如果目前容器不存在這個 BeanDefinition,試試父容器中有沒有
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// 傳回父容器的查詢結果
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
if (!typeCheckOnly) {
// 将目前 beanName 放入一個 alreadyCreated 的 Set 集合中。
// 辨別本次調用方法,并非是要擷取bean的類型,而是為了建立執行個體,将beanName存到alreadyCreated集合,代表該bean已經建立了,後面try。。catch有異常會清空該beanName
markBeanAsCreated(beanName);
}
// 到這裡的話,要準備建立 Bean 了,對于 singleton 的 Bean 來說,容器中還沒建立過此 Bean ,對于 prototype 的 Bean 來說,本來就是要建立一個新的 Bean。
try {
// 從容器中擷取beanName對應的GenericBeanDefinition對象,并轉換成RootBeanDefinition對象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 檢查合并的BeanDefinition,是否為抽象類
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 先初始化depens-on依賴
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若給定的依賴bean已經注冊為依賴給定的bean
// 即循環依賴情況,抛出BeanCreationException異常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 注冊依賴關系
registerDependentBean(dep, beanName);
// 遞歸處理依賴 Bean
getBean(dep);
}
}
// Create bean instance.
// 處理singleton
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
// 執行建立 Bean,詳情繼續深入
// 第三個參數 args 數組代表建立執行個體需要的參數,不就是給構造方法用的參數,或者是工廠 Bean 的參數嘛,不過要注意,在我們的初始化階段,args 是 null。
// 這回我們要到一個新的類了 AbstractAutowireCapableBeanFactory,看類名,AutowireCapable?類名是不是也說明了點問題了。
// 主要是為了以下場景,采用 @Autowired 注解注入屬性值:
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
// 顯式從單例緩存中删除Bean執行個體
// 因為單例模式下為了解決循環依賴,可能它已經存在,是以銷毀它
destroySingleton(beanName);
throw ex;
}
});
// 下面這個方法:如果是普通 Bean 的話,直接傳回 sharedInstance,
// 如果是 FactoryBean 的話,傳回它建立的那個執行個體對象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 如果是 prototype scope 的,建立 prototype 的執行個體
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
// 前置處理
beforePrototypeCreation(beanName);
// 執行建立 Bean
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
// 後置處理
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; consider " +
"defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
// Check if required type matches the type of the actual bean instance.
// 最後,檢查一下類型對不對,不對的話就抛異常,對的話就傳回了
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}
總結一下這個方法幹了些啥:
- 根據傳進來的 BeanName 擷取一個正統的 Bean 名稱,為啥這用做,傳進來的有可能是别名或者帶 & 字首的,是以要先擷取 Bean 的正統名稱才能繼續。
- 先從單例緩存池中擷取一次 Bean,判斷是否已經建立過,如果是則在判斷是否為 FactoryBean 進而判斷時傳回擷取到的 Bean 本身還是 FactoryBean 中的 getObject 值。
- 判斷是否出現循環引用問題,如果是多例模式則報錯,解決不了這種循環引用問題。
- 判斷是否已經加載過該 Bean
- 将要開始建立的 Bean 名稱放入 alreadyCreated 屬性集合中,表示至少建立過一次 Bean
- 判斷該 Bean 是否有 DependsOn 依賴,如果有,則先建立依賴
- 判斷是單例 Bean ,調用 getSingleton 方法開始真正的建立 Bean
- 判斷是多例 Bean ,調用 createBean 方法開始真正的建立 Bean
- 兩者都不是則直接調用 createBean 建立 Bean
- 檢查建立出來的 Bean 類型是否正确
這裡要注意的是循環引用的判斷,Spring 不會去解決多例 Bean 的循環引用問題。
然後我們就要進入代碼分析的重點了,即單例 Bean 的初始化流程 getSingleton 方法。
方法源碼
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
// beanName 不能為空
Assert.notNull(beanName, "Bean name must not be null");
// 同步
synchronized (this.singletonObjects) {
// 從緩存中檢查一遍
// 因為 singlton 模式其實已經複用了建立的bean,是以該步驟必須檢查
Object singletonObject = this.singletonObjects.get(beanName);
// 為空,開始進行建立
if (singletonObject == null) {
// 如果目前建立的 Bean 是銷毀狀态則報錯
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
// 加載前置處理 其實就是打一個标記,向 singletonsCurrentlyInCreation 中添加正在建立的beanName
beforeSingletonCreation(beanName);
// 首先将新的newSingleton設定為false
boolean newSingleton = false;
// 異常存放集合
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 真正去建立 Bean ,調用 singletonFactory 中的實作方法 getObject,這其實是個回調方法,回調傳入進來的 createBean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 一堆異常處理後,進行後置處理 移除标志
afterSingletonCreation(beanName);
}
// 新的bean 加入緩存中
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
// 傳回建立的 B
return singletonObject;
}
}
在 getSingleton 方法中有一個參數 singletonFactory 它的類型為一個函數式接口,既在上代碼中 singletonFactory.getObject() 代碼就是去調用 singletonFactory 接口中的實作方法,也就是我們傳入進來的匿名内部類,也既 createBean 方法。
createBean 方法顧名思義就是去建立 Bean 的,方法源碼
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
// 判斷需要建立的Bean是否可以執行個體化,即是否可以通過目前的類加載器加載
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
// 如果resolvedClass存在,并且mdb的beanClass類型不是Class,并且mdb的beanClass不為空(則代表beanClass存的是Class的name),
// 則使用mdb深拷貝一個新的RootBeanDefinition副本,并且将解析的Class指派給拷貝的RootBeanDefinition副本的beanClass屬性,
// 該拷貝副本取代mdb用于後續的操作
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 驗證及準備覆寫的方法(對override屬性進行标記及驗證)
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 執行個體化前的處理,給InstantiationAwareBeanPostProcessor一個機會傳回代理對象來替代真正的bean執行個體,達到“短路”效果
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
// 如果bean不為空,則會跳過Spring預設的執行個體化過程,直接使用傳回的bean
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 建立Bean執行個體(真正建立Bean的方法)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
// 傳回建立的Bean執行個體
return beanInstance;
}
catch (BeanCreationException ex) {
// A previously detected exception with proper bean creation context already...
throw ex;
}
catch (ImplicitlyAppearedSingletonException ex) {
// An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry...
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
我們可以看到這裡面有兩個重要的方法:
- resolveBeforeInstantiation:是否需要傳回代理對象
- doCreateBean:真正去建立 Bean
這裡先不讨論 AOP 代理相關的流程,直接進入 doCreateBean 方法源碼:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// 建立Bean包裝類
BeanWrapper instanceWrapper = null;
// 如果RootBeanDefinition是單例的,則移除未完成的FactoryBean執行個體的緩存
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 根據beanName、mbd、args,使用對應的政策建立Bean執行個體,并傳回包裝類BeanWrapper
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 拿到建立好的Bean執行個體
final Object bean = instanceWrapper.getWrappedInstance();
// 拿到Bean執行個體的類型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 應用後置處理器MergedBeanDefinitionPostProcessor,允許修改MergedBeanDefinition,
// Autowired注解正是通過此方法實作注入類型的預解析
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 判斷是否需要提早曝光執行個體:單例 && 允許循環依賴 && 目前bean正在建立中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 提前曝光beanName的ObjectFactory,用于解決循環引用
// 應用後置處理器SmartInstantiationAwareBeanPostProcessor,允許傳回指定bean的早期引用,若沒有則直接傳回bean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
// 初始化bean執行個體
Object exposedObject = bean;
try {
// 對bean進行屬性填充;其中,可能存在依賴于其他bean的屬性,則會遞歸初始化依賴的bean執行個體
populateBean(beanName, mbd, instanceWrapper);
// 對bean進行初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
if (earlySingletonExposure) {
// 如果允許提前曝光執行個體,則進行循環依賴檢查
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference隻有在目前解析的bean存在循環依賴的情況下才會不為空
if (earlySingletonReference != null) {
if (exposedObject == bean) {
// 如果exposedObject沒有在initializeBean方法中被增強,則不影響之前的循環引用
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// 如果exposedObject在initializeBean方法中被增強 && 不允許在循環引用的情況下使用注入原始bean執行個體
// 目前bean有被其他bean依賴
// 拿到依賴目前bean的所有bean的beanName數組
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// 嘗試移除這些bean的執行個體,因為這些bean依賴的bean已經被增強了,他們依賴的bean相當于髒資料
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
// 移除失敗的添加到 actualDependentBeans
actualDependentBeans.add(dependentBean);
}
}
// 如果存在移除失敗的,則抛出異常,因為存在bean依賴了“髒資料”
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
// 注冊用于銷毀的bean,執行銷毀操作的有三種:自定義destroy方法、DisposableBean接口、DestructionAwareBeanPostProcessor
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 完成建立并傳回
return exposedObject;
}
總結一下這個方法幹了些啥:
- 如果是單例則需要首先清除緩存
- 執行個體化 bean ,将 BeanDefinition 轉換為 BeanWrapper
- 應用後置處理器 MergedBeanDefinitionPostProcessor
- 是否提早暴露對象,解決循環依賴
- 對 bean 進行屬性填充
- 對 bean 進行初始化,比如 init-method
- 循環依賴檢查
- 将 Bean 注冊進用于銷毀的容器中,友善容器銷毀統一調用銷毀方法
- 完成建立并傳回
這個方法做了非常多的事情,且每個步驟都是我們需要去搞懂了解的,是以下面對這些步驟逐一分析。
1.1 建立 Bean 執行個體
createBeanInstance方法源碼
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 解析bean的類型資訊
Class<?> beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
// beanClass不為空 && beanClass不是公開類(不是public修飾) && 該bean不允許通路非公共構造函數和方法,則抛異常
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果存在工廠方法則使用工廠方法執行個體化bean對象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// resolved: 構造函數或工廠方法是否已經解析過
boolean resolved = false;
// autowireNecessary: 是否需要自動注入(即是否需要解析構造函數參數)
boolean autowireNecessary = false;
if (args == null) {
// 加鎖
synchronized (mbd.constructorArgumentLock) {
// 如果resolvedConstructorOrFactoryMethod緩存不為空,則将resolved标記為已解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// 根據constructorArgumentsResolved判斷是否需要自動注入
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 如果已經解析過,則使用resolvedConstructorOrFactoryMethod緩存裡解析好的構造函數方法
if (autowireNecessary) {
// 需要自動注入,則執行構造函數自動注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 否則使用預設的構造函數進行bean的執行個體化
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 應用後置處理器SmartInstantiationAwareBeanPostProcessor,拿到bean的候選構造函數
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 如果ctors不為空 || mbd的注入方式為AUTOWIRE_CONSTRUCTOR || mdb定義了構造函數的參數值 || args不為空,則執行構造函數自動注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 沒有特殊處理,則使用預設的構造函數進行bean的執行個體化
return instantiateBean(beanName, mbd);
}
該方法先确定構造器或工廠方法是否被解析過,如果是則不進行解析過程,直接調用對應的方法将對象傳回。如果未解析則判斷是否存在工廠方法,是則調用工廠方法進行執行個體化對象進行傳回,反之則進行非常複雜的構造器推斷邏輯找出需要執行執行個體化的構造器方法,将對象建立出來并進行方法。
推到構造器的三個重要方法:
- determineConstructorsFromBeanPostProcessors:擷取所有候選構造器
- autowireConstructor:構造器自動注入
- instantiateBean:預設構造器進行 Bean 執行個體化
因為 autowireConstructor 方法非常複雜,這裡就不進行分析了,而 instantiateBean 建立對象的方式較為簡單就也不在這裡講解。
1.2 後置處理器的應用 MergedBeanDefinitionPostProcessor
方法源碼
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
進入
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors
protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
// 擷取BeanFactory中已注冊的BeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof MergedBeanDefinitionPostProcessor) {
MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
// 調用MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition方法
// 重點關注AutowiredAnnotationBeanPostProcessor,該類會把@Autowired等标記的
// 需要依賴注入的成員變量或者方法執行個體給記錄下來,友善後續populateBean使用
bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
}
}
}
應用後置處理器 MergedBeanDefinitionPostProcessor,允許修改RootBeanDefinition,Autowired注解、Value注解正是通過此方法實作注入類型的預解析。
如 Autowired 解析源碼
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#postProcessMergedBeanDefinition
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
// 找到要自動裝配的資訊
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
// 設定到 bd 中,完成預解析
metadata.checkConfigMembers(beanDefinition);
}
1.3 提早暴露對象,解決循環依賴
提早暴露對象,就是向三級緩存中添加剛建立出來的對象,僅此而已。
入口代碼:
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
這行代碼分兩個方法
- addSingletonFactory:向三級緩存中添加提前暴露的對象
- getEarlyBeanReference:三級緩存中存放的對象是 singletonFactory ,是以拿到三級緩存中的元素調用 getObject 方法時,會來調用這個方法,傳回真正的對象。
三級緩存相關代碼如下:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
/** Cache of singleton objects: bean name to bean instance. */
//一級緩存:單例對象緩存池,beanName->Bean,其中存儲的就是執行個體化,屬性指派成功之後的單例對象
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name to ObjectFactory. */
//三級緩存:單例工廠的緩存,beanName->ObjectFactory,添加進去的時候執行個體還未具備屬性
// 用于儲存beanName和建立bean的工廠之間的關系map,單例Bean在建立之初過早的暴露出去的Factory,
// 為什麼采用工廠方式,是因為有些Bean是需要被代理的,總不能把代理前的暴露出去那就毫無意義了
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name to bean instance. */
// 二級緩存:早期的單例對象,beanName->Bean,其中存儲的是執行個體化之後,屬性未指派的單例對象
// 執行了工廠方法生産出來的Bean,bean被放進去之後,
// 那麼當bean在建立過程中,就可以通過getBean方法擷取到
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
/** Set of registered singletons, containing the bean names in registration order. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
// 1.如果beanName不存在于singletonObjects緩存中
if (!this.singletonObjects.containsKey(beanName)) {
//往三級緩存裡添加
// 2.将beanName和singletonFactory注冊到singletonFactories緩存(beanName -> 該beanName的單例工廠)
this.singletonFactories.put(beanName, singletonFactory);
//清除此Bean在二級緩存裡的緩存資訊
// 3.移除earlySingletonObjects緩存中的beanName(beanName -> beanName的早期單例對象)
this.earlySingletonObjects.remove(beanName);
// 這裡為了記錄注冊單例的順序
// 4.将beanName注冊到registeredSingletons緩存(已經注冊的單例集合)
this.registeredSingletons.add(beanName);
}
}
}
}
這個方法很簡單,就是向 singletonFactories 集合中添加我們傳進來的類型為 ObjectFactory 的匿名内部類,并清除二級緩存中的資訊,最後在記錄到 registeredSingletons 集合中。
下面我們看看 ObjectFactory 中的 getObject 方法的實作類源碼(匿名内部類的實作)
getEarlyBeanReference 方法源碼
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getEarlyBeanReference
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
// 如果bean不為空 && mbd不是合成 && 存在InstantiationAwareBeanPostProcessors
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
// 應用所有SmartInstantiationAwareBeanPostProcessor,調用getEarlyBeanReference方法
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
// 允許SmartInstantiationAwareBeanPostProcessor傳回指定bean的早期引用
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
// 傳回要作為bean引用公開的對象,如果沒有SmartInstantiationAwareBeanPostProcessor修改,則傳回的是入參的bean對象本身
return exposedObject;
}
我們可以看到如果 Spring 中沒有 SmartInstantiationAwareBeanPostProcessor 類型相關的後置處理器則相當于下面這段代碼:
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
return exposedObject;
}
那麼如果有呢!先看 SmartInstantiationAwareBeanPostProcessor 類的繼承結構圖
可以看到有兩個預設實作 AbstractAutoProxyCreator 和 InstantiationAwareBeanPostProcessorAdapter ,而真正會對 getEarlyBeanReference 方法做動作的隻有 AbstractAutoProxyCreator ,是以我們自然而然的要去看它了。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
this.earlyProxyReferences.add(cacheKey);
}
// 如果需要代理,傳回一個代理對象,不需要代理,直接傳回目前傳入的這個bean對象
return this.wrapIfNecessary(bean, beanName, cacheKey);
}
可以看出,這個方法就是進行 AOP 代理的,那這裡我們留到 AOP 代理相關的内容進行分析。
1.4 對 Bean 屬性進行填充
入口
populateBean(beanName, mbd, instanceWrapper)
方法源碼
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// bw為空時的處理
if (bw == null) {
// 如果bw為空,屬性不為空,抛異常,無法将屬性值應用于null執行個體
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
// 如果bw為空,屬性也為空,則跳過
return;
}
}
// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
// state of the bean before properties are set. This can be used, for example,
// to support styles of field injection.
// 給InstantiationAwareBeanPostProcessors最後一次機會在屬性注入前修改Bean的屬性值,也可以控制是否繼續填充Bean
// 具體通過調用postProcessAfterInstantiation方法,如果調用傳回false,表示不必繼續進行依賴注入,直接傳回
// 主要是讓使用者可以自定義屬性注入。比如使用者實作一個 InstantiationAwareBeanPostProcessor 類型的後置處理器,
// 并通過 postProcessAfterInstantiation 方法向 bean 的成員變量注入自定義的資訊。
boolean continueWithPropertyPopulation = true;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
// 如果mbd不是合成的 && 存在InstantiationAwareBeanPostProcessor,則周遊處理InstantiationAwareBeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
// 在bean執行個體化後,屬性填充之前被調用,允許修改bean的屬性,如果傳回false,則跳過之後的屬性填充
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 如果後置處理器發出停填充指令則終止後續的執行
if (!continueWithPropertyPopulation) {
return;
}
// pvs是一個MutablePropertyValues執行個體,裡面實作了PropertyValues接口,
// 提供屬性的讀寫操作實作,同時可以通過調用構造函數實作深拷貝
// 擷取BeanDefinition裡面為Bean設定上的屬性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 根據bean的依賴注入方式:即是否标注有 @Autowired 注解或 autowire=“byType/byName” 的标簽
// 會周遊bean中的屬性,根據類型或名稱來完成相應的注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
// 深拷貝目前已有的配置
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根據beanName進行autowiring自動裝配處理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根據Bean的類型進行autowiring自動裝配處理
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
// 結合注入後的配置,覆寫目前配置
pvs = newPvs;
}
// BeanFactory是否注冊過InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否進行依賴檢查,預設為false
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
// 注冊過InstantiationAwareBeanPostProcessors 或者 需要依賴檢查
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
// 應用後置處理器InstantiationAwareBeanPostProcessor
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
// 依賴檢查,對應depend-on屬性,3.0已經棄用此屬性
// 檢查是否滿足相關依賴關系,對應的depends-on屬性,需要確定所有依賴的Bean先完成初始化
if (needsDepCheck) {
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 最終将屬性注入到Bean的Wrapper執行個體裡,這裡的注入主要是供
// 顯式配置了autowiredbyName或者ByType的屬性注入,
// 針對注解來講,由于在AutowiredAnnotationBeanPostProcessor已經完成了注入,
// 是以此處不執行
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
這個方法幹了寫啥:
- 對 BeanWrapper 進行檢查,若 BeanWrapper 為空,屬性不為空則報錯,反之跳過
- 判斷是否有 InstantiationAwareBeanPostProcessor 類型後置處理器,有就執行 postProcessAfterInstantiation 方法進行屬性填充(該方法傳回結果能影響後續屬性填充)
- 根據Bean配置的依賴注入方式完成注入(autowireByName、autowireByType)
- 判斷是否有 InstantiationAwareBeanPostProcessor 類型後置處理器,有則執行相關方法進行依賴校驗
- 依賴檢查,對應depend-on屬性
- 應用屬性的值(指派操作)
1.5 對 Bean 進行初始化
入口
exposedObject = initializeBean(beanName, exposedObject, mbd);
方法源碼
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
// 激活Aware方法
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()) {
// 在初始化前應用BeanPostProcessor的postProcessBeforeInitialization方法,允許對bean執行個體進行包裝
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()) {
// 在初始化後應用BeanPostProcessor的postProcessAfterInitialization方法,允許對bean執行個體進行包裝
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
// 傳回wrappedBean
return wrappedBean;
}
這個方法是對我們的 Bean 進行初始化的,主要執行了以下幾個方法:
- invokeAwareMethods(beanName, bean):執行各種 XXXAware 接口方法
- applyBeanPostProcessorsBeforeInitialization:執行 BeanPostProcessor 類型的 postProcessBeforeInitialization 方法
- invokeInitMethods(beanName, wrappedBean, mbd):執行如 init-method 相關方法
- applyBeanPostProcessorsAfterInitialization:執行 BeanPostProcessor 類型的 postProcessAfterInitialization 方法
到此,我們的 finishBeanFactoryInitialization 方法算是全部分析完畢了,Spring 中所有的單例 Bean 也從定義資訊變成了一個真正的 Bean 對象了。
最後,畫圖小能手上線,Bean 加載全流程圖:
二、refresh 方法之 finishRefresh
該方法是 refresh 重新整理方法的第十二個方法,表明此方法執行完之後,Spring 就算是啟動完成了。
那我們看看該方法幹了些啥事情:
org.springframework.context.support.AbstractApplicationContext#finishRefresh
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
// 清除資源緩存
clearResourceCaches();
// Initialize lifecycle processor for this context.
// 為此上下文初始化生命周期處理器
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
// 首先将重新整理完畢事件傳播到生命周期處理器(觸發isAutoStartup方法傳回true的SmartLifecycle的start方法)
getLifecycleProcessor().onRefresh();
// Publish the final event.
// 推送上下文重新整理完畢事件到相應的監聽器
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
- 清空資源緩存
- 初始化生命周期處理器,預設是DefaultLifecycleProcessor,并作為單例注冊到容器
- 觸發DefaultLifecycleProcessor的onRefresh方法,簡單來講就是觸發那些實作了Lifecycle的bean的start方法并将running狀态設定為true
- 釋出事件ContextRefreshedEvent,表明上下文重新整理完成
- 注冊ApplicationContext到LiveBeansView内部的applicationContexts中