Spring IOC的深入理解(五)

引言

在執行ac.getBean("car")的過程中,spring如何加載bean的?

FactoryBean

public interface FactoryBean<T>
{
//......
}

當配置文件<bean>中的class的類是FactoryBean接口的實現類時,getBean返回的就不是對應的類,而是這個實現類調用get
Object()方法所返回的對象,相當于是getObject()代理了getBean()類

從緩存中獲取單例類

單例在spring中只會創建一次,后續獲取bean直接從單例緩存中獲取,首先嘗試從緩存中加載,后序在嘗試從SingletonFactories中獲取.
Spring創建bean的原則就是在創建一個bean時候,不等bean創建完成就將ObjectFactory提早曝光到緩存中.下次有bean依賴到這個已經創建的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,然后調用這個singletonFactory來創建singletonObject,然后放到earlySingletonObjects中去,然后從singletonFactories清除掉這個beanName.
其中有大量的map,我們來進行梳理一下:

  • singletonObjects bean和BeanName的關系如果其中有bean,就可以直接創建
  • singletonFactories BeanName和Bean工廠之間的關系
  • earlySingletonObjects BeanName和bean,主要是用來做循環檢驗的

這個時候我們就獲取到了beanName對應的bean了

從bean的實例中獲取對象

如果緩存不為空的話,我們就已經獲取到實例了,記住這個時候我們是從緩存中獲取的實例,然后我們繼續回到最開始的方法

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類型的,然后調用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();之后回到上一層代碼,會調用如下的一段代碼

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;
    }

這個就是后處理器的使用,在后面我們會詳細的介紹

創建單例

    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);都是用來記錄加載狀態的,最后將緩存假加入到緩存中,并刪除一些緩存記錄.
我們已經了解了bean的邏輯架構,真正的bean加載過程是在傳入的匿名內部類中實現的

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方法中的后處理的調用,
bean在實例化前會有一個后處理器的調用,將AbstractBeanDefinition轉化成BeanWrapper,經過處理這有可能是一個經過處理的bean,而后處理的過程,就是將bean注冊的過程,當bean再次使用時,就不必在進行創建了

創建bean

然后我們進入到doCreateBean方法中,這里是常規的bean操作.
如果是單例,首先需要清除緩存.實例化bean,將BeanDefinition轉換為BeanWrapper.使用工廠方法,使用構造方法,使用默認構造方法

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。