Spring IoC源碼執行流程解析

這篇文章是我學習spring IoC 分析其源碼時總結的,其目的並不是是徹底理解源碼信息,可是根據spring IoC 容器如何從xml文件到bean的實例初始化進行了一個流程的梳理,但願能夠對你們理解源碼有必定的幫助。話很少少,咱們直接來看。 html

這裏,我是用ApplicationContext來進行介紹,畢竟項目中大部分仍是使用的這個容器。容器啓動的入口咱們能夠從AbstractApplicationContext類的refresh方法看起。
Spring IoC容器對Bean定義資源的載入是從refresh()函數開始的,refresh()是一個模板方法,refresh()方法的做用是:在建立IoC容器前,若是已經有容器存在,則須要把已有的容器銷燬和關閉,以保證在refresh以後使用的是新創建起來的IoC容器。refresh的做用相似於對IoC容器的重啓,在新創建好的容器中對容器進行初始化,對Bean定義資源進行載入。 spring

refreshsql

public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            prepareRefresh();

            // Tell the subclass to refresh the internal bean factory.
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // Prepare the bean factory for use in this context.
            prepareBeanFactory(beanFactory);

            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();
            }

            catch (BeansException ex) {
                // Destroy already created singletons to avoid dangling resources.
                destroyBeans();

                // Reset 'active' flag.
                cancelRefresh(ex);

                // Propagate exception to caller.
                throw ex;
            }
        }
    }

上邊有兩個很重要的方法:數據庫

  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    這個方法就是根據Xml配置文件解析Bean的信息生成BeanDifinition,而後註冊到BeanDefinitionRegistry中,即bean信息的裝載註冊階段
  • beanFactory.preInstantiateSingletons();
    這個方法看其註釋咱們就能夠理解,它是實例化全部非懶加載的單例bean。

AbstractApplicationContext的obtainFreshBeanFactory()方法調用子類容器的refreshBeanFactory()方法,啓動容器載入Bean定義資源文件的過程,代碼以下:bootstrap

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {  
        //這裏使用了委派設計模式,父類定義了抽象的refreshBeanFactory()方法,具體實現調用子類容器的refreshBeanFactory()方法
         refreshBeanFactory();  
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();  
        if (logger.isDebugEnabled()) {  
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);  
        }  
        return beanFactory;  
    }

AbstractApplicationContext類中只抽象定義了refreshBeanFactory()方法,容器真正調用的是其子類AbstractRefreshableApplicationContext實現的 refreshBeanFactory()方法。代碼以下:設計模式

protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            synchronized (this.beanFactoryMonitor) {
                this.beanFactory = beanFactory;
            }
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

在這個方法中,先判斷BeanFactory是否存在,若是存在則先銷燬beans並關閉beanFactory,接着建立DefaultListableBeanFactory,並調用loadBeanDefinitions(beanFactory)裝載bean定義。 緩存

咱們在其子類AbstractXmlApplicationContext最終能夠看到下面這個方法,此方法就是真正從XML文件中讀取並解析Bean的信息,放在對應的BeanDefinition中app

protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setEnvironment(this.getEnvironment());
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

再看preInstantiateSingletons()ide

public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isInfoEnabled()) {
            this.logger.info("Pre-instantiating singletons in " + this);
        }
        List<String> beanNames;
        synchronized (this.beanDefinitionMap) {
            // 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.
            beanNames = new ArrayList<String>(this.beanDefinitionNames);
        }
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            public Boolean run() {
                                return ((SmartFactoryBean<?>) factory).isEagerInit();
                            }
                        }, getAccessControlContext());
                    }
                    else {
                        isEagerInit = (factory instanceof SmartFactoryBean &&
                                ((SmartFactoryBean<?>) factory).isEagerInit());
                    }
                    if (isEagerInit) {
                        getBean(beanName);
                    }
                }
                else {
                    getBean(beanName);
                }
            }
        }
    }

其中咱們須要關注getBean(beanName)這個方法,此方法中進行了bean的實例化和初始化;咱們能夠進入這個方法中,看到doGetBean() 這個方法函數

protected <T> T doGetBean(
            final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
            throws BeansException {
            ... ...  
            //這一部分是先從緩存中獲取對應的bean;若是有的話,返回緩存中的單例bean;
            Object sharedInstance = getSingleton(beanName);
        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 = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        
        else {
        
        ... ...
        /**
            * Return a merged RootBeanDefinition, traversing the parent bean definition
            * if the specified bean corresponds to a child bean definition.
            */
        final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
        
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dependsOnBean : dependsOn) {
                    getBean(dependsOnBean);
                    registerDependentBean(dependsOnBean, beanName);
                }
            }

            // Create bean instance.
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    public Object getObject() throws BeansException {
                        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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
        }
            }

上邊的代碼中,咱們須要關心的是

  • final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    獲取到對應beanName的BeanDefinition,這裏顯然是作了些包裝(RootBeanDefinition);
  • 因爲在項目中,絕大部分bean都是單例的,因此咱們只關心單例類型的bean的建立
if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    public Object getObject() throws BeansException {
                        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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

注意,這裏從新 實現了ObjectFactory中的getObject()方法,這個對下面的理解有很大幫助。咱們先進入getSingleton()方法中

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized (this.singletonObjects) {
            //從緩存中獲取對應的bean
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName,
                            "Singleton bean creation not allowed while the 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 recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<Exception>();
                }
                try {
                    singletonObject = singletonFactory.getObject();
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                //在這裏將實例化的bean放入容器中;
                addSingleton(beanName, singletonObject);
            }
            return (singletonObject != NULL_OBJECT ? singletonObject : null);
        }
    }

這裏邊咱們須要關注的有

  • beforeSingletonCreation(beanName);
    從名稱咱們大概能夠猜出來這個方法的一些做用:在單例bean建立以前所要作的事;
  • singletonObject = singletonFactory.getObject();
    看到這裏,你會想到什麼?前面所說的在上一層從新實現了次方法,因此這一塊得注意,它執行的是從新實現後的方法,等下具體分析。
  • afterSingletonCreation(beanName);
    對應beforeSingletonCreation,這個就是在單例bean建立以後所要作的事;

接下來,咱們回頭看一下從新實現的singletonFactory.getObject()裏調用了createBean(beanName, mbd, args);

咱們進入createBean(beanName, mbd, args)

protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
            throws BeanCreationException {

        if (logger.isDebugEnabled()) {
            logger.debug("Creating instance of bean '" + beanName + "'");
        }
        // Make sure bean class is actually resolved at this point.
        resolveBeanClass(mbd, beanName);

        // Prepare method overrides.
        try {
            mbd.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
            Object bean = resolveBeforeInstantiation(beanName, mbd);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        Object beanInstance = doCreateBean(beanName, mbd, args);
        if (logger.isDebugEnabled()) {
            logger.debug("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }

在這裏,咱們能夠看到

Object beanInstance = doCreateBean(beanName, mbd, args);

在這個方法中進行備案的實例化(有人這時候會說,怎麼這麼就尚未看到真正的bean實例化,沒辦法,spring本身還要實現本身的一些東西,這些咱們不關注,可是不表明沒有必要,因此耐心看下去吧)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// Instantiate the bean.
        //這個類將做爲最終的bean單例放入容器中
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
        Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                mbd.postProcessed = true;
            }
        }

        // Eagerly cache singletons to be able to resolve circular references
        // even when triggered by lifecycle interfaces like BeanFactoryAware.
        //處理循環依賴的問題
        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");
            }
            addSingletonFactory(beanName, new ObjectFactory() {
                public Object getObject() throws BeansException {
                    return getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

// Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                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);
            }
        }
        
... ... 

}

此方法較長,咱們只須要關心咱們須要關心的。

  • BeanWrapper instanceWrapper = null;
    此類將做爲最終的單例bean放入容器中,這個類將會是對應bean的一個封裝;
  • applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
    容許其餘修改beanDefinition,這主要是容許其餘組件提供xml不能提供的信息。如使用Annotation加強Bean定義等。這經過類ergedBeanDefinitionPostProcessor來完成,若是容器中提供了此類實現,則會調用進行bean加強。
  • populateBean(beanName, mbd, instanceWrapper);
    此方法裏是利用InstantiationAwareBeanPostProcessor將bean進行填充,以及autowire標籤的處理
  • exposedObject = initializeBean(beanName, exposedObject, mbd);
    重頭戲來了,這個纔是咱們最要關心的,在裏邊會進行bean的實例化和初始化

進入initializeBean

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            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()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }
        return wrappedBean;
    }

這裏邊有三個重要的方法

  • invokeAwareMethods(beanName, bean);
    查看該bean是否實現了相關的Aware接口,若是有,將其進行裝配;
  • wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  • invokeInitMethods(beanName, wrappedBean, mbd);
    這裏利用Java反射機制將bean對應的beanDefinition信息進行設置;
  • wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

spring提供了一個接口類-BeanPostProcessor,咱們叫他:bean的加工器,應該是在bean的實例化過程當中對bean作一些包裝處理,裏邊提供兩個方法applyBeanPostProcessorsBeforeInitialization和applyBeanPostProcessorsAfterInitialization。

根據以上代碼,咱們得知,在invokeInitMethods的執行先後,spring會分別調用全部的BeanPostProcessor,執行其中的方法,那麼invokeInitMethods的具體內容咱們仍須要看下,發現此方法主要做用有兩個:

  1. 判斷bean是否繼承了InitializingBean,若是繼承接口,執行afterPropertiesSet()方法
  2. 得到是否設置了init-method屬性,若是設置了,就執行設置的方法

這裏幾個典型的應用場景如:

  1. 解析bean的註解,將註解中的字段轉化爲屬性
  2. 統一將屬性在執行前,注入bean中,如數據庫訪問的sqlMap,如嚴重服務,這樣不須要每一個bean都配置屬性
  3. 打印日誌,記錄時間等。
    詳細瞭解BeanPostProcessor的使用能夠參考這裏BeanPostProcessor的使用

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
                ((InitializingBean) bean).afterPropertiesSet();
            }
        }

        if (mbd != null) {
            String initMethodName = mbd.getInitMethodName();
            if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                    !mbd.isExternallyManagedInitMethod(initMethodName)) {
                invokeCustomInitMethod(beanName, bean, mbd);
            }
        }
    }

到了這裏,spring才真正地實例化並初始化bean。 因此在進入initializeBean方法裏,咱們大概能夠總結出bean的初始化順序:
XXAware接口的實現->postProcessBeforeInitialization->InitializingBean的afterPropertiesSet -> custom Init方法->postProcessAfterInitialization

若有錯誤,歡迎指正。若是對你有幫助的話,順便點個贊哈!

相關文章
相關標籤/搜索