詳解Spring 如何創(chuàng)建 Bean 對象?
前情回顧前文「Spring 如何從 IoC 容器中獲取對象?」從整體上分析了如何從 Spring IoC 容器獲取一個(gè) bean 對象。該邏輯由 AbstractBeanFactory#doGetBean 方法實(shí)現(xiàn),主要流程如下:

本文進(jìn)一步深入細(xì)節(jié),主要分析如何創(chuàng)建 singleton(單例)類型的對象。
如何創(chuàng)建單例對象?
從流程圖可以看出,當(dāng)獲取一個(gè) bean 對象時(shí),Spring 會首先嘗試從緩存中獲取單例對象。
值得注意是的:
- 只有對象是單例的場景,即 scope 為 singleton 時(shí)才會緩存對象。
- 這里其實(shí)涉及到了所謂的「三級緩存」,為了更容易理解三級緩存,本文先研究這個(gè) bean 對象是什么時(shí)候放入緩存的,后面再研究三級緩存。
既然能取,必然有地方把 bean 對象存入了緩存,那緩存中的數(shù)據(jù)是從哪里來的呢?
下面主要分析單例對象是如何創(chuàng)建、并放入緩存中的。
該邏輯在 AbstractBeanFactory#doGetBean 方法中,主要代碼如下(保留了創(chuàng)建單例 bean 對象的代碼,其他部分暫時(shí)忽略):
- public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
- // ...
- protected <T> T doGetBean(
- String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
- throws BeansException {
- String beanName = transformedBeanName(name);
- Object bean;
- // 從緩存中獲取單例 bean 對象
- Object sharedInstance = getSingleton(beanName);
- // 緩存中不存在 bean 對象
- else {
- // ...
- try {
- // 獲取 BeanDefinition
- RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
- // 獲取依賴的 bean 對象
- // 若創(chuàng)建一個(gè) bean 對象時(shí)依賴其他對象,則先創(chuàng)建被依賴對象
- // ...
- // 創(chuàng)建 scope 為 singleton(單例)的對象
- if (mbd.isSingleton()) {
- sharedInstance = getSingleton(beanName, () -> {
- try {
- return createBean(beanName, mbd, args);
- }
- catch (BeansException ex) {
- // ...
- }
- });
- // 處理 FactoryBean 的場景
- bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
- }
- // 創(chuàng)建 scope 為 prototype 的對象
- else if (mbd.isPrototype()) {
- // ...
- }
- // 創(chuàng)建其他類型對象
- else {
- // ...
- }
- }
- catch (BeansException ex) {
- // ...
- }
- }
- // 類型檢查
- return (T) bean;
- }
- }
其實(shí)就是這個(gè) DefaultSingletonBeanRegistry#getSingleton 方法,代碼如下:
- public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
- // 單例 bean 對象緩存(beanName, bean)
- private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
- public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
- Assert.notNull(beanName, "Bean name must not be null");
- synchronized (this.singletonObjects) {
- // 先從緩存中獲取 bean 對象
- Object singletonObject = this.singletonObjects.get(beanName);
- // 緩存中不存在時(shí)再去創(chuàng)建
- if (singletonObject == null) {
- // ...
- // 創(chuàng)建單例對象前
- beforeSingletonCreation(beanName);
- boolean newSingleton = false;
- boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
- if (recordSuppressedExceptions) {
- this.suppressedExceptions = new LinkedHashSet<>();
- }
- try {
- // 創(chuàng)建單例對象
- singletonObject = singletonFactory.getObject();
- newSingleton = true;
- }
- // catch ...
- finally {
- if (recordSuppressedExceptions) {
- this.suppressedExceptions = null;
- }
- // 創(chuàng)建單例對象后
- afterSingletonCreation(beanName);
- }
- if (newSingleton) {
- // 將對象添加到緩存
- addSingleton(beanName, singletonObject);
- }
- }
- // 緩存中有的話直接返回
- return singletonObject;
- }
- }
- }
getSingleton 方法會先從緩存 singletonObjects(其實(shí)就是一個(gè) Map)中獲取 bean 對象,如果緩存有就直接返回,否則再去創(chuàng)建。創(chuàng)建成功后,會把該對象存入緩存。
創(chuàng)建的邏輯在哪呢?
看代碼是通過 ObjectFactory#getObject 方法來創(chuàng)建的,ObjectFactory 是一個(gè)函數(shù)式接口:
- @FunctionalInterface
- public interface ObjectFactory<T> {
- T getObject() throws BeansException;
- }
這個(gè)方法的實(shí)現(xiàn)是什么呢?退回上一層,即 getBean 方法,看這里:
- sharedInstance = getSingleton(beanName, () -> {
- try {
- // 創(chuàng)建 bean 對象
- return createBean(beanName, mbd, args);
- }
- catch (BeansException ex) {
- // ...
- }
- });
這里用到了 Lambda 表達(dá)式,將如下表達(dá)式作為參數(shù):
- () -> {
- try {
- // 創(chuàng)建 bean 對象
- return createBean(beanName, mbd, args);
- }
- catch (BeansException ex) {
- // ...
- }
- }
創(chuàng)建 bean 對象的邏輯就在這個(gè) createBean 方法中,它在 AbstractAutowireCapableBeanFactory 類中:
- public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
- implements AutowireCapableBeanFactory {
- @Override
- protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- throws BeanCreationException {
- RootBeanDefinition mbdToUse = mbd;
- Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
- if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
- mbdToUse = new RootBeanDefinition(mbd);
- mbdToUse.setBeanClass(resolvedClass);
- }
- // Prepare method overrides.
- try {
- mbdToUse.prepareMethodOverrides();
- }
- // catch ...
- try {
- // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
- // 這里可能返回代理對象
- Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
- if (bean != null) {
- return bean;
- }
- }
- // catch ...
- try {
- // 創(chuàng)建 bean 對象
- Object beanInstance = doCreateBean(beanName, mbdToUse, args);
- if (logger.isTraceEnabled()) {
- logger.trace("Finished creating instance of bean '" + beanName + "'");
- }
- return beanInstance;
- }
- // catch ...
- }
- }
- 值得注意的是,resolveBeforeInstantiation 方法其實(shí)是跟 AOP 實(shí)現(xiàn)相關(guān)的,可能在這里生成代理對象就返回了。由于現(xiàn)在主要分析 IoC 的流程,因此這里暫時(shí)略過,有興趣的朋友們可以自行研究。
這里繼續(xù)沿著主線邏輯走。
創(chuàng)建 bean 對象是在 doCreateBean 方法中實(shí)現(xiàn)的,如下:
- public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
- implements AutowireCapableBeanFactory {
- protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
- throws BeanCreationException {
- // Instantiate the bean.
- // 1. 實(shí)例化 bean
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- Object bean = instanceWrapper.getWrappedInstance();
- 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 {
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- }
- // catch ...
- mbd.postProcessed = true;
- }
- }
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
- isSingletonCurrentlyInCreation(beanName));
- if (earlySingletonExposure) {
- addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- // 2. 填充屬性
- populateBean(beanName, mbd, instanceWrapper);
- // 3. 初始化
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- // catch ...
- if (earlySingletonExposure) {
- Object earlySingletonReference = getSingleton(beanName, false);
- if (earlySingletonReference != null) {
- if (exposedObject == bean) {
- exposedObject = earlySingletonReference;
- }
- else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
- String[] dependentBeans = getDependentBeans(beanName);
- Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
- for (String dependentBean : dependentBeans) {
- if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
- actualDependentBeans.add(dependentBean);
- }
- }
- // ...
- }
- }
- }
- // Register bean as disposable.
- try {
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- }
- // catch ...
- return exposedObject;
- }
- }
- 注意:Instantiate 和 Initialize 雖然看起來有點(diǎn)像,但它倆不是一回事,前者是“實(shí)例化”,后者是“初始化”。
這個(gè)方法看起來有點(diǎn)長,但最主要的事情只有三件:
- 創(chuàng)建 bean 對象:createBeanInstance 方法
- 填充屬性:populateBean 方法
- 初始化 bean:initializeBean 方法
這幾個(gè)方法內(nèi)部其實(shí)都有一大堆堆堆堆堆……的代碼,再對照一下前面給出的整體流程圖 :
就是這樣。
本文在前文整體分析的基礎(chǔ)上又進(jìn)一步細(xì)化,先到這里吧,后面再繼續(xù)分析~
小結(jié)
如何從 Spring IoC 容器中獲取 bean 對象?前文對此進(jìn)行了整體流程的分析。
本文在前文的基礎(chǔ)上又進(jìn)一步細(xì)化,主要從整體上探討了 Spring 如何創(chuàng)建單例的 bean 對象,整體上分為三個(gè)步驟:
- 創(chuàng)建 bean 對象。
- 填充 bean 屬性
- 初始化 bean 對象
至于這三個(gè)步驟具體又做了什么,且聽下回分解。