Spring版本
5.2.5.RELEASE
參考
Spring-IOC-容器源碼分析-創(chuàng)建單例-bean
源碼解析
在上一篇《Spring源碼解析-獲取單例bean》中,在doGetBean
的最后,調(diào)用了getSingleton
方法,并且將beanName
和一個返回createBean
方法的匿名方法作為參數(shù)傳入:
sharedInstance = getSingleton(beanName, () -> {
try {
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.
// 在早期的創(chuàng)建過程中解滓,可能為了解決循環(huán)引用問題,導(dǎo)致beanName加入了singleton緩存中兴溜,此時需要移除該緩存
destroySingleton(beanName);
throw ex;
}
});
那么我們先看看getSingleton
方法
1. DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
// 從緩存中獲取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
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
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// 這里的getObject方法實(shí)際上調(diào)用的是singletonFactory匿名函數(shù)的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.
// createBean方法有可能拋出ImplicitlyAppearedSingletonException異常
// 該異常是IllegalStateException的子類约啊,當(dāng)這種異常出現(xiàn)的時候耗帕,此時bean可能已經(jīng)被隱含地(implicitly)實(shí)例化
// 所以這一步需要再從singletonObjects這個已實(shí)例化的集合匯總獲取一次實(shí)例化對象
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;
}
// 從singletonsCurrentlyInCreation移除
afterSingletonCreation(beanName);
}
if (newSingleton) {
// 針對singleton做一些緩存方面的處理,如加入<beanName,bean>的緩存忠售、從早起引用map中移除等
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
首先從緩存中獲取bean實(shí)例传惠,如果存在,直接返回稻扬,否則進(jìn)行創(chuàng)建的流程卦方。
這里面入?yún)?code>singletonFactory是一個函數(shù)式接口參數(shù):
@FunctionalInterface
public interface ObjectFactory<T> {
/**
* Return an instance (possibly shared or independent)
* of the object managed by this factory.
* @return the resulting instance
* @throws BeansException in case of creation errors
*/
T getObject() throws BeansException;
}
因此,singletonFactory.getObject()
實(shí)際上就是調(diào)用createBean
方法
2. AbstractAutowireCapableBeanFactory#createBean
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isTraceEnabled()) {
logger.trace("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.
// 確認(rèn)到了這一步bean類型已經(jīng)被解析泰佳,以防動態(tài)解析class的情況下盼砍,mdb的beanClass屬性為空
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
// 處理look-up method和replace method
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.
// 看英文注釋這里是給BeanPostProcessors一個機(jī)會返回一個代理對象而不是bean實(shí)例
// 但是resolveBeforeInstantiation內(nèi)部代碼感覺又沒有進(jìn)去執(zhí)行具體邏輯,具體后面解析
// TODO
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
// 真正創(chuàng)建bean實(shí)例
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
1逝她、通過resolveBeanClass
解析mdb的beanClass
屬性
2衬廷、處理了lookup-method和replace-method倆種注入,關(guān)于這倆種注入方法汽绢,可以戳:14--Spring lookup-method注入和replace-method注入(二)
3、通過resolveBeforeInstantiation
給BeanPostProcessor
一個機(jī)會返回代理對象
4侧戴、最后調(diào)用了doCreateBean
進(jìn)行創(chuàng)建
2.1 AbstractAutowireCapableBeanFactory#resolveBeanClass
@Nullable
protected Class<?> resolveBeanClass(final RootBeanDefinition mbd, String beanName, final Class<?>... typesToMatch)
throws CannotLoadBeanClassException {
try {
// 如果mbd已經(jīng)解析出beanClass宁昭,直接返回
if (mbd.hasBeanClass()) {
return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ->
doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
}
else {
// 否則,進(jìn)行解析邏輯
return doResolveBeanClass(mbd, typesToMatch);
}
}
catch (PrivilegedActionException pae) {
ClassNotFoundException ex = (ClassNotFoundException) pae.getException();
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (ClassNotFoundException ex) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex);
}
catch (LinkageError err) {
throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err);
}
}
-
mbd
已經(jīng)有beanClass
酗宋,那么直接返回 - 否則积仗,調(diào)用
doResolveBeanClass
進(jìn)行解析
2.2 AbstractAutowireCapableBeanFactory#doResolveBeanClass
@Nullable
private Class<?> doResolveBeanClass(RootBeanDefinition mbd, Class<?>... typesToMatch)
throws ClassNotFoundException {
ClassLoader beanClassLoader = getBeanClassLoader();
ClassLoader dynamicLoader = beanClassLoader;
boolean freshResolve = false;
if (!ObjectUtils.isEmpty(typesToMatch)) {
// When just doing type checks (i.e. not creating an actual instance yet),
// use the specified temporary class loader (e.g. in a weaving scenario).
ClassLoader tempClassLoader = getTempClassLoader();
if (tempClassLoader != null) {
dynamicLoader = tempClassLoader;
freshResolve = true;
if (tempClassLoader instanceof DecoratingClassLoader) {
DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader;
for (Class<?> typeToMatch : typesToMatch) {
dcl.excludeClass(typeToMatch.getName());
}
}
}
}
// 獲取文本類型的className,通過className和classLoader來獲取beanClass
String className = mbd.getBeanClassName();
if (className != null) {
// 貌似是解析SPEL表達(dá)式的蜕猫,這塊沒看懂
Object evaluated = evaluateBeanDefinitionString(className, mbd);
// 如果倆者不相同寂曹,說明使用了SPEL表達(dá)式
if (!className.equals(evaluated)) {
// A dynamically resolved expression, supported as of 4.2...
if (evaluated instanceof Class) {
return (Class<?>) evaluated;
}
else if (evaluated instanceof String) {
className = (String) evaluated;
freshResolve = true;
}
else {
throw new IllegalStateException("Invalid class name expression result: " + evaluated);
}
}
if (freshResolve) {
// When resolving against a temporary class loader, exit early in order
// to avoid storing the resolved Class in the bean definition.
if (dynamicLoader != null) {
try {
// dynamicLoader不為空,通過dynamicLoader
return dynamicLoader.loadClass(className);
}
catch (ClassNotFoundException ex) {
if (logger.isTraceEnabled()) {
logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex);
}
}
}
// 如果dynamicLoader為空回右,通過forName進(jìn)行加載
return ClassUtils.forName(className, dynamicLoader);
}
}
// Resolve regularly, caching the result in the BeanDefinition...
// 如果className為空隆圆,進(jìn)行常規(guī)加載(該方法內(nèi)部其實(shí)也是通過ClassUtils.forName(className, classLoader))
return mbd.resolveBeanClass(beanClassLoader);
}
獲取string類型的className,加載獲得對應(yīng)的class
1.3 AbstractAutowireCapableBeanFactory#doCreateBean
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
// 單例模型翔烁,則從未完成的 FactoryBean 緩存中刪除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// 使用合適的實(shí)例化策略來創(chuàng)建新的實(shí)例:工廠方法渺氧、構(gòu)造函數(shù)自動注入、簡單初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 判斷是否需要應(yīng)用后置處理器
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
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.
// 這里是早期引用的邏輯蹬屹,用于解決單例模式的循環(huán)引用侣背,需要滿足一下三個條件:
// 1、單例模式
// 2慨默、開啟早期引用
// 3贩耐、beanName正在創(chuàng)建中(A依賴B,B依賴A厦取,先創(chuàng)建A潮太,發(fā)現(xiàn)依賴B,去創(chuàng)建B虾攻,結(jié)果發(fā)現(xiàn)依賴A消别,又再去創(chuàng)建A)
// 第三點(diǎn)解釋如下:
// 情景:A依賴B抛蚤,B依賴A
// 過程:
// 1、創(chuàng)建A寻狂,走到這一步岁经,A沒有處于創(chuàng)建中,earlySingletonExposure此時為false蛇券,繼續(xù)往下走缀壤,將A正在創(chuàng)建中寫入singletonsCurrentlyInCreation
// 2、發(fā)現(xiàn)依賴B纠亚,去創(chuàng)建B
// 3塘慕、創(chuàng)建B,走到這一步蒂胞,B也沒有處于創(chuàng)建中图呢,同步驟一繼續(xù)往下走
// 4、發(fā)現(xiàn)依賴A骗随,去創(chuàng)建A
// 5蛤织、創(chuàng)建A,此時鸿染,A已經(jīng)處于singletonsCurrentlyInCreation了指蚜,此時滿足條件,進(jìn)入if分支
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 解決循環(huán)引用涨椒,提前將bean實(shí)例寫入singletonFactories摊鸡、earlySingletonObjects和registeredSingletons
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充屬性
populateBean(beanName, mbd, instanceWrapper);
// 實(shí)例化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) {
// addSingletonFactory中已經(jīng)將bean加入earlySingletonObjects中,這里從中獲取
Object earlySingletonReference = getSingleton(beanName, false);
// 只有循環(huán)依賴的情況下if分支的條件才會成立
if (earlySingletonReference != null) {
// exposedObject初始賦值便是bean蚕冬,那么說明其沒有被initializeBean方法改變
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// allowRawInjectionDespiteWrapping:是否在循環(huán)依賴的情況下重新整理成原生bean
// 個人理解是為了解決循環(huán)依賴問題免猾,之前使用了早期引用,
// 而一旦allowRawInjectionDespiteWrapping為true囤热,那么就將該早期引用替換成原聲bean
// 不過這里的allowRawInjectionDespiteWrapping是false的情況下else if分支成立
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
// alreadyCreated 不包含dependentBean的情況下if分支成立
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
// 如果alreadyCreated包含任何一個dependentBean掸刊,那么這里if分支成立,此時拋出異常
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銷毀邏輯
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
1赢乓、使用createBeanInstance
創(chuàng)建一個instanceWrapper
忧侧,詳見《Spring源碼解析(九)-創(chuàng)建bean實(shí)例》
2、應(yīng)用后置BeanPostProcessor
3牌芋、解決單例模式下循環(huán)引用的問題
4蚓炬、通過populateBean
填充屬性,詳見《Spring源碼解析(十)-填充bean屬性》
5躺屁、通過initializeBean
應(yīng)用init-method
方法肯夏,詳見《Spring源碼解析(十一)-初始化bean》
6、實(shí)例化depends on
對應(yīng)的bean
7、調(diào)用registerDisposableBeanIfNecessary
注冊bean的銷毀邏輯驯击,詳見《Spring源碼解析(十二)-注冊bean銷毀邏輯》
8烁兰、返回創(chuàng)建完畢的bean實(shí)例
總結(jié)
創(chuàng)建單例bean的核心都在doCreateBean
方法中,該方法分別實(shí)現(xiàn)了創(chuàng)建bean實(shí)例徊都、應(yīng)用BeanPostProcessors
沪斟、解決循環(huán)引用問題、填充bean屬性暇矫、應(yīng)用init-method
方法主之、實(shí)例化depends on
對應(yīng)的bean和注冊bean銷毀邏輯等功能,內(nèi)容較多李根,需要逐個慢慢解析擊破