引言
在執(zhí)行ac.getBean("car")的過程中,spring如何加載bean的?
FactoryBean
public interface FactoryBean<T>
{
//......
}
當配置文件<bean>中的class的類是FactoryBean接口的實現(xiàn)類時,getBean返回的就不是對應的類,而是這個實現(xiàn)類調(diào)用get
Object()方法所返回的對象,相當于是getObject()代理了getBean()類
從緩存中獲取單例類
單例在spring中只會創(chuàng)建一次,后續(xù)獲取bean直接從單例緩存中獲取,首先嘗試從緩存中加載,后序在嘗試從SingletonFactories中獲取.
Spring創(chuàng)建bean的原則就是在創(chuàng)建一個bean時候,不等bean創(chuàng)建完成就將ObjectFactory提早曝光到緩存中.下次有bean依賴到這個已經(jīng)創(chuàng)建的bean的時候,就直接使用ObjectFactory
Object sharedInstance = getSingleton(beanName);
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
首先查看緩存中是否有實例,如果有就獲取
如果沒有的話,全局加鎖,在從earlySingletonObjects中獲取,如果還是獲取不到,就從singletonFactories中獲取BeanName對應的ObjectFactory,然后調(diào)用這個singletonFactory來創(chuàng)建singletonObject,然后放到earlySingletonObjects中去,然后從singletonFactories清除掉這個beanName.
其中有大量的map,我們來進行梳理一下:
- singletonObjects bean和BeanName的關系如果其中有bean,就可以直接創(chuàng)建
- singletonFactories BeanName和Bean工廠之間的關系
- earlySingletonObjects BeanName和bean,主要是用來做循環(huán)檢驗的
這個時候我們就獲取到了beanName對應的bean了
從bean的實例中獲取對象
如果緩存不為空的話,我們就已經(jīng)獲取到實例了,記住這個時候我們是從緩存中獲取的實例,然后我們繼續(xù)回到最開始的方法
if (sharedInstance != null && args == null) {
if (logger.isTraceEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
我們進入到這個方法中
這個代碼大概的意思就是,嘗試從緩存中獲取加載bean,如果加載失敗,我們就可以明確的知道是Factorybean類型的,然后調(diào)用getObjectFromFactoryBean這個方法,其中doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
throws BeanCreationException {
Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
object = factory.getObject();之后回到上一層代碼,會調(diào)用如下的一段代碼
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;
}
這個就是后處理器的使用,在后面我們會詳細的介紹
創(chuàng)建單例
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.
destroySingleton(beanName);
throw ex;
}
});
上面講的是從緩沖中獲取單例bean,然后從bean的實例中獲取對象.接下來就是如果緩存中沒有bean,我們該怎么辦,我們進入到這個重載的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 + "'");
}
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
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);
}
if (newSingleton) {
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
其中singletonObject = singletonFactory.getObject();是初始化bean的,我們來看看在它之前都做了些什么?檢查和記錄
beforeSingletonCreation(beanName);和 afterSingletonCreation(beanName);都是用來記錄加載狀態(tài)的,最后將緩存假加入到緩存中,并刪除一些緩存記錄.
我們已經(jīng)了解了bean的邏輯架構,真正的bean加載過程是在傳入的匿名內(nèi)部類中實現(xiàn)的
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
我們來深入了解createBean方法.
首先是解析Class,然后是對override方法進行標記和驗證
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
try {
mbdToUse.prepareMethodOverrides();
}
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
applyBeanPostProcessorsBeforeInstantiation和applyBeanPostProcessorsAfterInitialization是對getSingleton方法中的后處理的調(diào)用,
bean在實例化前會有一個后處理器的調(diào)用,將AbstractBeanDefinition轉(zhuǎn)化成BeanWrapper,經(jīng)過處理這有可能是一個經(jīng)過處理的bean,而后處理的過程,就是將bean注冊的過程,當bean再次使用時,就不必在進行創(chuàng)建了
創(chuàng)建bean
然后我們進入到doCreateBean方法中,這里是常規(guī)的bean操作.
如果是單例,首先需要清除緩存.實例化bean,將BeanDefinition轉(zhuǎn)換為BeanWrapper.使用工廠方法,使用構造方法,使用默認構造方法