溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring這么初始化Bean實(shí)例對象

發(fā)布時間:2022-03-19 10:22:41 來源:億速云 閱讀:151 作者:iii 欄目:云計算

這篇文章主要介紹了Spring這么初始化Bean實(shí)例對象的相關(guān)知識,內(nèi)容詳細(xì)易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Spring這么初始化Bean實(shí)例對象文章都會有所收獲,下面我們一起來看看吧。

代碼入口

DefaultListableBeanFactory的preInstantiateSingletons方法

DefaultListableBeanFactory的preInstantiateSingletons方法,顧名思義,初始化所有的單例Bean,看一下方法的定義:

public void preInstantiateSingletons() throws BeansException {

    if (this.logger.isInfoEnabled()) {

        this.logger.info("Pre-instantiating singletons in " + this);

    }

    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.

        List<String> 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);

                }

            }

        }

    }

}

前面的代碼比較簡單,根據(jù)beanName拿到BeanDefinition(即Bean的定義)。由于此方法實(shí)例化的是所有非懶加載的單例Bean,因此要實(shí)例化Bean,必須滿足11行的三個定義:

(1)不是抽象的

(2)必須是單例的

(3)必須是非懶加載的

接著簡單看一下第12行~第29行的代碼,這段代碼主要做的是一件事情:首先判斷一下Bean是否FactoryBean的實(shí)現(xiàn),接著判斷Bean是否SmartFactoryBean的實(shí)現(xiàn),假如Bean是SmartFactoryBean的實(shí)現(xiàn)并且eagerInit(這個單詞字面意思是渴望加載,找不到一個好的詞語去翻譯,意思就是定義了這個Bean需要立即加載的意思)的話,會立即實(shí)例化這個Bean。Java開發(fā)人員不需要關(guān)注這段代碼,因為SmartFactoryBean基本不會用到,我翻譯一下Spring官網(wǎng)對于SmartFactoryBean的定義描述:

  • FactoryBean接口的擴(kuò)展接口。接口實(shí)現(xiàn)并不表示是否總是返回單獨(dú)的實(shí)例對象,比如FactoryBean.isSingleton()實(shí)現(xiàn)返回false的情況并不清晰地表示每次返回的都是單獨(dú)的實(shí)例對象

     

  • 不實(shí)現(xiàn)這個擴(kuò)展接口的簡單FactoryBean的實(shí)現(xiàn),F(xiàn)actoryBean.isSingleton()實(shí)現(xiàn)返回false總是簡單地告訴我們每次返回的都是單獨(dú)的實(shí)例對象,暴露出來的對象只能夠通過命令訪問

     

  • 注意:這個接口是一個有特殊用途的接口,主要用于框架內(nèi)部使用與Spring相關(guān)。通常,應(yīng)用提供的FactoryBean接口實(shí)現(xiàn)應(yīng)當(dāng)只需要實(shí)現(xiàn)簡單的FactoryBean接口即可,新方法應(yīng)當(dāng)加入到擴(kuò)展接口中去

代碼示例

為了后面的代碼分析方便,事先我定義一個Bean:

package org.xrq.action;

 

import org.springframework.beans.factory.BeanClassLoaderAware;

import org.springframework.beans.factory.BeanNameAware;

import org.springframework.beans.factory.InitializingBean;

 

public class MultiFunctionBean implements InitializingBean, BeanNameAware, BeanClassLoaderAware {

 

    private int    propertyA;

 

    private int    propertyB;

 

    public int getPropertyA() {

        return propertyA;

    }

 

    public void setPropertyA(int propertyA) {

        this.propertyA = propertyA;

    }

 

    public int getPropertyB() {

        return propertyB;

    }

 

    public void setPropertyB(int propertyB) {

        this.propertyB = propertyB;

    }

 

    public void initMethod() {

        System.out.println("Enter MultiFunctionBean.initMethod()");

    }

 

    @Override

    public void setBeanClassLoader(ClassLoader classLoader) {

        System.out.println("Enter MultiFunctionBean.setBeanClassLoader(ClassLoader classLoader)");

    }

 

    @Override

    public void setBeanName(String name) {

        System.out.println("Enter MultiFunctionBean.setBeanName(String name)");

    }

 

    @Override

    public void afterPropertiesSet() throws Exception {

        System.out.println("Enter MultiFunctionBean.afterPropertiesSet()");

    }

 

    @Override

    public String toString() {

        return "MultiFunctionBean [propertyA=" + propertyA + ", propertyB=" + propertyB + "]";

    }

 

}

定義對應(yīng)的spring.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://www.springframework.org/schema/beans

 

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

 

    <bean id="multiFunctionBean" class="org.xrq.action.MultiFunctionBean" init-method="initMethod" />

 

</beans>

利用這個MultiFunctionBean,我們可以用來探究Spring加載Bean的多種機(jī)制。

doGetBean方法構(gòu)造Bean流程

上面把getBean之外的代碼都分析了一下,看代碼就可以知道,獲取Bean對象實(shí)例,都是通過getBean方法,getBean方法最終調(diào)用的是DefaultListableBeanFactory的父類AbstractBeanFactory類的doGetBean方法,因此這部分重點(diǎn)分析一下doGetBean方法是如何構(gòu)造出一個單例的Bean的。

看一下doGetBean方法的代碼實(shí)現(xiàn),比較長:

protected <T> T doGetBean(

        final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

        throws BeansException {

 

    final String beanName = transformedBeanName(name);

    Object bean;

 

    // Eagerly check singleton cache for manually registered singletons.

    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 {

        // Fail if we're already creating this bean instance:

        // We're assumably within a circular reference.

        if (isPrototypeCurrentlyInCreation(beanName)) {

            throw new BeanCurrentlyInCreationException(beanName);

        }

 

        // Check if bean definition exists in this factory.

        BeanFactory parentBeanFactory = getParentBeanFactory();

        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

            // Not found -> check parent.

            String nameToLookup = originalBeanName(name);

            if (args != null) {

                // Delegation to parent with explicit args.

                return (T) parentBeanFactory.getBean(nameToLookup, args);

            }

            else {

                // No args -> delegate to standard getBean method.

                return parentBeanFactory.getBean(nameToLookup, requiredType);

            }

        }

 

        if (!typeCheckOnly) {

            markBeanAsCreated(beanName);

        }

 

        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() {

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

        }

 

        else if (mbd.isPrototype()) {

            // It's a prototype -> create a new instance.

            Object prototypeInstance = null;

            try {

                beforePrototypeCreation(beanName);

                prototypeInstance = createBean(beanName, mbd, args);

            }

            finally {

                afterPrototypeCreation(beanName);

            }

            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);

        }

 

        else {

            String scopeName = mbd.getScope();

            final Scope scope = this.scopes.get(scopeName);

            if (scope == null) {

                throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");

            }

            try {

                Object scopedInstance = scope.get(beanName, new ObjectFactory() {

                    public Object getObject() throws BeansException {

                            beforePrototypeCreation(beanName);

                        try {

                            return createBean(beanName, mbd, args);

                        }

                        finally {

                            afterPrototypeCreation(beanName);

                        }

                    }

                });

                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

            }

            catch (IllegalStateException ex) {

                throw new BeanCreationException(beanName,

                        "Scope '" + scopeName + "' is not active for the current thread; " +

                        "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",

                        ex);

            }

        }

    }

 

    // Check if required type matches the type of the actual bean instance.

    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {

        try {

            return getTypeConverter().convertIfNecessary(bean, requiredType);

        }

        catch (TypeMismatchException ex) {

            if (logger.isDebugEnabled()) {

                logger.debug("Failed to convert bean '" + name + "' to required type [" +

                        ClassUtils.getQualifiedName(requiredType) + "]", ex);

            }

            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());

        }

    }

    return (T) bean;

}

關(guān)于“Spring這么初始化Bean實(shí)例對象”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“Spring這么初始化Bean實(shí)例對象”知識都有一定的了解,大家如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI