spring源碼閱讀(1/4) - Bean生成

上午去繳了上次沒帶駕駛證的扣分罰款,最近在圖書館沒事就看曾國藩家書,曾國藩說人要明強。光強沒有用,你要明強。也就是說要強的有道理。曾國藩又說,作學問不能作死學問,作學問其實很重要的事就是能懂得孝悌,把家持好,能作事。能作事很重要,學問再高,不能作事,也是無用。相反即便沒什麼學問,寫不出來,可是能作事,事事作的條理,家庭安排的和氣,家族事宜可以有積極的貢獻,再到更大的方面,都能作好,這纔是學問的意義。看了一下,上一篇文章已是2號的了,這個月已經9號了,1/3了,但是這重頭的Bean加載尚未什麼大的進展,這樣怎麼能行,家裏的事情還要辦,不少事情還沒弄好,這可不行呀。面試

想要人生有所突破,下一番苦工是不可能省略的。一半努力一半爲所欲爲,是不可能成就的。spring

「須是策勵此心,勇猛奮發,撥出心肝與他去作!如兩邊擂起戰鼓,莫問前頭如何,只認卷將去!如此,方作得工夫。若半上落下,半沉半浮,濟得甚事!」 朱熹 .《朱子語錄》緩存

咱們繼續上節的內容,這節主要是bean的加載。app

咱們從ServerMain的方法中的getBean("")做爲入口來看:ide

public Object getBean(String name) throws BeansException {
        return this.doGetBean(name, (Class)null, (Object[])null, false);
    }

繼續調用,都在AbstractBeanFactory中進行,下邊這段就是恐怖的bean加載了。咱們能夠翻到最後看下返回了Bean,固然bean是範性的,先拋開中間的過程不說,這裏返回的就是實實在在的咱們須要的Bean了,彷佛一切都在這個方法裏,沒錯全部的「恩怨」都在這裏。函數

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        final String beanName = this.transformedBeanName(name);
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            if (this.logger.isDebugEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = this.getParentBeanFactory();
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }

            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;

                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dependsOnBean = var11[var13];
                        if (this.isDependent(beanName, dependsOnBean)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dependsOnBean + "'");
                        }

                        this.registerDependentBean(dependsOnBean, beanName);
                        this.getBean(dependsOnBean);
                    }
                }

                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    String scopeName = mbd.getScope();
                    Scope 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<Object>() {
                            public Object getObject() throws BeansException {
                                AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                                Object var1;
                                try {
                                    var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                                } finally {
                                    AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                                }

                                return var1;
                            }
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var21) {
                        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", var21);
                    }
                }
            } catch (BeansException var23) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var23;
            }
        }

        if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
            try {
                return this.getTypeConverter().convertIfNecessary(bean, requiredType);
            } catch (TypeMismatchException var22) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Failed to convert bean '" + name + "' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

好,下邊咱們就開始這場江湖的血雨腥風。post

首先第一句就是:ui

final String beanName = this.transformedBeanName(name);

這句作的事情,好像不知道所云,由於beanName不是做爲參數傳進來了嗎,還要再轉換是什麼意思,稍微想一下就知道了,咱們獲取bean的時候傳過來的name參數,有多是別名。this

若是是別名這裏就須要轉換一下了,由於咱們須要真正的名稱。spa

翻看下代碼:

protected String transformedBeanName(String name) {
        return this.canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }

括號裏邊的部分的代碼以下:

public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");

        String beanName;
        for(beanName = name; beanName.startsWith("&"); beanName = beanName.substring("&".length())) {
        }

        return beanName;
    }

若是name是以&開頭的,那麼去除開頭的&符號。繼續:

public String canonicalName(String name) {
        String canonicalName = name;

        String resolvedName;
        do {
            resolvedName = (String)this.aliasMap.get(canonicalName);
            if (resolvedName != null) {
                canonicalName = resolvedName;
            }
        } while(resolvedName != null);

        return canonicalName;
    }

這裏很容易看出來,就是根據名稱去別名map中獲取有沒有對應的名稱。目的就是獲取別名對應的真實Bean名稱。

接下來這句getSingleton就涉及到偉大的又扯淡的各類面試都會問到的循環依賴問題了,其實不復雜,可是沒認真研究過代碼。關於循環依賴的問題,能夠看下個章節。這裏重點仍是建立Bean這個主題。

咱們繼續上邊的doCreateBean(name, requiredType, args[], typeCheckOnly)的代碼。轉換完名字以後,緊接的一句是getSingleton(beanName).

@Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    /**
     * Return the (raw) singleton object registered under the given name.
     * <p>Checks already instantiated singletons and also allows for an early
     * reference to a currently created singleton (resolving a circular reference).
     * @param beanName the name of the bean to look for
     * @param allowEarlyReference whether early references should be created or not
     * @return the registered singleton object, or {@code null} if none found
     */
    @Nullable
    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;
    }

這裏咱們觀察註釋,可以瞭解一部分:返回已這個beanName註冊的實例。而且檢查已經初始化的實例,容許當前建立的實例有一個早期的引用(用來解決循環依賴問題)。

咱們深刻代碼來看一下:

首先從singletonObjects.get(beanName)從緩存裏獲取一下,看有沒有,若是有直接返回。若是沒有,而且當前beanName正在建立,那麼加鎖後邊的這部分代碼:

判斷beanName是否在earlySingletonObjects列表中,若是不在而且容許早期引用,那麼就獲取beanName對應的ObjectFactory。而後調用ObjectFactory.getObject()返回實例。並將該實例添加到earlySingletonObjects中。這裏確實就是解決循環引用的核心了,解決循環依賴的核心就是這裏的這個singletonFactories.get(beanName)獲取singletonFactory,而後調用getOjbect返回實例。說的通俗一點兒就是可能對象尚未建立,可是可以建立這個對象的ObjectFactroy會提早放入緩存中,這樣,當後續建立過程當中,須要引用一個以前尚未建立完的bean時,就會調用這裏的ObjectFactory.getObject()返回一個實例對象。

這個部分咱們在下一篇專門將循環依賴的文章裏詳細闡述。在這裏,這個getSingleton在總體流程上,最核心的是從緩存中嘗試獲取bean。

咱們繼續看下代碼,咱們用粗體標示了一個方法:getObjectForBeanInstance(scopedInstance, name, beanName, mdb)。咱們看到,後續的幾種狀況裏,不管是singleton/prototype/仍是其餘實例模式,獲得bean以後,作的事情都是這個getObjectForBeanInstance方法,咱們來跟進看下:

    /** 獲取給定bean實例的對象,要麼bean實例自己,要麼當它是一個FactroyBean時,它建立出來的對象
     **/
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

        // 若是指定的name是&開頭即工廠相關的,但又不是FactoryBean類型,則拋出異常,類型驗證不經過
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
            }
        }
// 如今咱們有個這個bean實例,可是這個bean實例多是普通bean也多是FactoryBean,若是是FactoryBean,那麼咱們使用它來獲取工廠實例,若是調用者須要的是
FactoryBean自己,那麼beanName參數須要帶"&"
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) { return beanInstance; } // 到這裏就明確是一個FactoryBean,由於若是不是上邊已經返回了 Object object = null; if (mbd == null) { object = getCachedObjectForFactoryBean(beanName); } if (object == null) { // Return bean instance from factory. FactoryBean<?> factory = (FactoryBean<?>) beanInstance; // Caches object obtained from FactoryBean if it is a singleton. if (mbd == null && containsBeanDefinition(beanName)) { mbd = getMergedLocalBeanDefinition(beanName); } boolean synthetic = (mbd != null && mbd.isSynthetic()); object = getObjectFromFactoryBean(factory, beanName, !synthetic); } return object; }

1:判斷是不是FactoryBean,判斷依據是 beanName是不是"&"開頭的。若是是&開頭,則表示是獲取FactoryBean自己,若是不是&開頭,則是獲取FactroyBean的方法返回的Bean。若是是&開頭,可是自己並非FactoryBean類型,則拋出異常。

2:若是自己不是FactoryBean類型或者beanName不是以「&」開頭的,那麼直接返回Bean自己。

3:判斷BeanDefinitions中是否存在該beanName。這裏作的事情實際上是將咱們解析時候生成的GenericBeanDefinition轉換成RootBeanDefinition.細節這裏就不說了。

4:最後委託給getObjectFromFactoryBean(factory, beanName, !synthetic)方法類獲取真正的實例。

咱們繼續往下看:

     /**  得到從給定的FactoryBean獲取出來的對象*/
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    object = doGetObjectFromFactoryBean(factory, beanName); // Only post-process and store if not put there already during getObject() call above
                    // (e.g. because of circular reference processing triggered by custom getBean calls)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (shouldPostProcess) {
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            beforeSingletonCreation(beanName);
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                            finally {
                                afterSingletonCreation(beanName);
                            }
                        }
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        }
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName); if (shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }

核心其實就是這句doGetObjectFromFactoryBean(factory, beanName)。裏邊的if裏是判斷是不是單例,而裏邊的內容跟else的區別就是若是是單例,那麼就嘗試從緩存中獲取,若是緩存中沒有才調用到doGetObjectFactoryBean(factory, beanName)。還有裏邊的beforeSingletonCreation和afterSingletonCreation則都是保證建立過程當中,不會重複建立實例,是爲了保證單例性。

好了,咱們仍是繼續一層一層的往下看吧。

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();
            }
        }
        catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        }
        catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }

        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }

終於到了最後獲取對象的地方了,這裏getObject()的調用爲整個經過FactoryBean獲取實例的解析過程畫上美麗的句號。

承接上文,咱們對緩存中獲取bean和FactoryBean方式獲取Bean進行了闡述。對getBean("")方法進行了闡述。這一篇咱們先深刻單例的建立來詳細說一下spring循環依賴問題的解決。

咱們從doGetBean方法繼續,咱們主要看下singleton這一部分:

// Create bean instance.
                if (mbd.isSingleton()) {
                    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 = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

咱們繼續getSingleton(beanName, singletonFactory)。

    /**
     * 返回beanName註冊過的單例對象,若是沒有,那麼建立並註冊該beanName的實例*/
    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); // 1 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); // 2 boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    singletonObject = singletonFactory.getObject(); // 3
                    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); // 4
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

這裏其實最核心的就是singletonFactory.getObject()。咱們梳理下步驟:

1:嘗試從緩存獲取beanName對應的bean

2:若是沒有,調用beforeSingletonCreation(beanName),將beanName放入singletonCurrentlyInCreation列表。

3:經過調用參數傳入的FactoryBean的getObject方法,獲取實例化bean

4:加載完成後,處理以後的方法調用。這裏作的事情跟beforeSingletonCreation正好相反,把beanName從singletonCurrentlyInCreation中刪除

5:緩存生成的object。並刪除生成過程當中的相關狀態。

/**
     * Add the given singleton object to the singleton cache of this factory.
     * <p>To be called for eager registration of singletons.
     * @param beanName the name of the bean
     * @param singletonObject the singleton object
     */
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject); // 放入緩存
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }

6:返回bean,這個bean就是上邊getSingleton(beanName, singletonFactory)的這個參數,在doGetBean中定義的方法。

                    sharedInstance = getSingleton(beanName, () -> { // 這裏是jdk8引入的函數是寫法,這裏其實就是ObjectFactroy的一個匿名類實現 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的代碼了。

咱們來詳細看下這個createBean(beanName, mdb, args)

/**
     * Central method of this class: creates a bean instance,
     * populates the bean instance, applies post-processors, etc.
     * @see #doCreateBean
     */
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;

        // Make sure bean class is actually resolv1ed at this point, and
        // clone the bean definition in case of a dynamically resolved Class
        // which cannot be stored in the shared merged bean definition.
        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 (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.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, mbdToUse); if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

1:根據mdb獲取beanName對應的class。

2:對override屬性進行處理

3:應用初始化前的處理器

4:建立bean

咱們來詳細看下override 的處理

/**
     * Validate and prepare the method overrides defined for this bean.
     * Checks for existence of a method with the specified name.
     * @throws BeanDefinitionValidationException in case of validation failure
     */
    public void prepareMethodOverrides() throws BeanDefinitionValidationException {
        // Check that lookup methods exists.
        if (hasMethodOverrides()) {
            Set<MethodOverride> overrides = getMethodOverrides().getOverrides();
            synchronized (overrides) {
                for (MethodOverride mo : overrides) {
                    prepareMethodOverride(mo);
                }
            }
        }
    }

    /**
     * Validate and prepare the given method override.
     * Checks for existence of a method with the specified name,
     * marking it as not overloaded if none found.
     * @param mo the MethodOverride object to validate
     * @throws BeanDefinitionValidationException in case of validation failure
     */
    protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
        int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
        if (count == 0) {
            throw new BeanDefinitionValidationException(
                    "Invalid method override: no method with name '" + mo.getMethodName() +
                    "' on class [" + getBeanClassName() + "]");
        }
        else if (count == 1) {
            // Mark override as not overloaded, to avoid the overhead of arg type checking.
            mo.setOverloaded(false);
        }
    }

這裏咱們要理解下lookup-method和override-method的問題。這兩個配置咱們在解析xml的時候說過但沒有太詳細介紹,這兩個的做用lookup-method。(這裏不太明白還,暫時放這裏,後續bean生成的時候看下到底代碼如何實現的,再過來看)

相關文章
相關標籤/搜索