基於AnnotationConfigApplicationContext的Bean加載過程(Spring Version 5.2.0)


建立個實體類

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class Book {

    private String name;

    public Book(String name) {
        this.name = name;
    }
}

再建立個配置類

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BookConfig {
    @Bean
    public Book book(){
        return new Book("BBB");
    }
}

最后是啟動程序

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(BookConfig.class);
        Book book = context.getBean(Book.class);
        System.out.println(book);
    }

}

主要看getBean的過程

1. 首先進入org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)

2. 進入org.springframework.context.support.GenericApplicationContext#getBeanFactory

3. 進入org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)

實際上調用的是重載方法getBean,在其中調用的是resolveBean方法,解析bean。

==========================================對比==========================================

等一等??看網上其它教程都會有個doGetBean的東西,到這里怎么沒有了?

我們知道目前常見的創建Application的方式有三種

FileSystemXmlApplicationContext/ClassPathXmlApplicationContext/AnnotationConfigApplicationContext

你以為我想說和上下文類型有關系?但是我告訴你和應用上下文的類型是沒有任何關系的!這三種主要的區別就是讀取配置的來源不同罷了,內部調用的都是refresh方法。

真正導致調用的方法不同,取決於你調用的是AbstractApplicationContext#getBean的哪一個重載方法。

第一個參數為String類型的getBean方法,最終會調用的AbstractBeanFactory#doGetBean

第一個參數為Class類型的getBean方法,最終會調用的DefaultListableBeanFactory#resolveBean

另外,后者resolveBean會調用doGetBean方法。

如紅框的會跑到AbstractBeanFactory類里

藍框的跑到DefaultListableBeanFactory類里

4. 根據傳入的Class,先封裝成ResolvableType。(對於指定的Class,返回一個ResolvableType,僅對原始類執行可分配性檢查,這是一個包裝器。)

5. 帶着ResolveableType進入org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean

@Nullable
private <T> T resolveBean(ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) {
    // 根據傳入的ResolvableType,返回一個NamedBeanHolder(一個持有bean名稱和bean實例的容器)
    NamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args, nonUniqueAsNull);
    // 如果namedBean不為空,則直接返回實例
    if (namedBean != null) {
        return namedBean.getBeanInstance();
    }
    // namedBean為空(比如我獲取了一個不存在的bean)則執行以下內容↓

    // 獲取父bean工廠
    BeanFactory parent = getParentBeanFactory();
    // 如果是DefaultListableBeanFactory的實例,則正常解析
    if (parent instanceof DefaultListableBeanFactory) {
        return ((DefaultListableBeanFactory) parent).resolveBean(requiredType, args, nonUniqueAsNull);
    }
    // 不是DefaultListableBeanFactory的實例並且不為空(這一步具體干啥還不清楚)
    else if (parent != null) {
        ObjectProvider<T> parentProvider = parent.getBeanProvider(requiredType);
        if (args != null) {
            return parentProvider.getObject(args);
        }
        else {
            return (nonUniqueAsNull ? parentProvider.getIfUnique() : parentProvider.getIfAvailable());
        }
    }
    // parent也為空,則返回空
    return null;
}

這個方法呢,主要調用了resolveNamedBean方法,利用返回持有名稱和實例的容器獲得bean實例。不是核心方法。

6. org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)

這個方法干的事情就比較多了

@SuppressWarnings("unchecked")
@Nullable
private <T> NamedBeanHolder<T> resolveNamedBean(
        ResolvableType requiredType, @Nullable Object[] args, boolean nonUniqueAsNull) throws BeansException {
    Assert.notNull(requiredType, "Required type must not be null");
    // 根據類型獲取bean名稱---①
    String[] candidateNames = getBeanNamesForType(requiredType);

    // 如果bean名稱不止一個(比如你定義了多個同類型但是名稱不一樣的Bean)
    if (candidateNames.length > 1) {
        // 自動裝配候選者列表
        List<String> autowireCandidates = new ArrayList<>(candidateNames.length);
        // 遍歷bean名稱
        for (String beanName : candidateNames) {
            // 判斷:如果beanDefinitionMap不包含key為beanName的鍵值對或者該bean可以被自動裝配到其他bean中。則添加到候選列表中
            if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {
                autowireCandidates.add(beanName);
            }
        }
        // 候選列表不為空,則給候選名稱重新賦值
        if (!autowireCandidates.isEmpty()) {
            candidateNames = StringUtils.toStringArray(autowireCandidates);
        }
    }
    // bean名稱只有一個
    if (candidateNames.length == 1) {
        // 因為只有一個,所以是0下標的名稱
        String beanName = candidateNames[0];
        // 返回一個持有bean名稱和bean實例的容器【getBean方法:繞了一圈,依然回到了AbstractBeanFactory#getBean,准確來說是doGetBean方法】---②
        return new NamedBeanHolder<>(beanName, (T) getBean(beanName, requiredType.toClass(), args));
    }
    else if (candidateNames.length > 1) {
        Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);
        // 遍歷候選名稱
        for (String beanName : candidateNames) {
            // 如果是單例並且args為空
            if (containsSingleton(beanName) && args == null) {
                // getBean實例化bean【getBean方法:繞了一圈,依然回到了AbstractBeanFactory#getBean,准確來說是doGetBean方法】
                Object beanInstance = getBean(beanName);
                // 放進候選Map里,value是bean實例
                candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));
            }
            else {
                // 否則直接范進Map里,value是bean的Class
                candidates.put(beanName, getType(beanName));
            }
        }
        // 因為這個方法只能返回一個實例,而這種情況我們獲取了多個,到底返回哪一個?
        // 這一步:確定給定bean集合中的主要候選對象。---③
        String candidateName = determinePrimaryCandidate(candidates, requiredType.toClass());
        if (candidateName == null) {
            // 這一步:確定給定bean集合中具有最高優先級的對象。---④
            candidateName = determineHighestPriorityCandidate(candidates, requiredType.toClass());
        }
        // 如果確定了返回哪一個對象
        if (candidateName != null) {
            // 從候選集合中選出目標對象
            Object beanInstance = candidates.get(candidateName);
            // 沒有實例化則實例化
            if (beanInstance == null || beanInstance instanceof Class) {
                beanInstance = getBean(candidateName, requiredType.toClass(), args);
            }
            // 返回包裝類
            return new NamedBeanHolder<>(candidateName, (T) beanInstance);
        }
        // 前面都沒確定出來,那只能拋異常了。
        if (!nonUniqueAsNull) {
            // 比如:No qualifying bean of type 'com.demo.tools.Book' available: expected single matching bean but found 2
            throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());
        }
    }
    return null;
}

總結:

1. 根據傳入的類型獲取bean的所有名稱。

2. 過濾候選bean名稱。

3. 如果bean名稱只有一個,那么直接調用AbstractBeanFactory里的doGetBean進行實例化並返回。

3. 如果bean名稱有多個,則選出主要候選名稱或者最高優先級的名稱來幫助實例化。如果沒有選出可用的名稱,則拋出bean定義沖突異常。

下面看一下其它方法:

①:根據類型獲取名稱列表

 

@Override
public String[] getBeanNamesForType(ResolvableType type) {
    return getBeanNamesForType(type, true, true);
}
@Override
public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    Class<?> resolved = type.resolve();
    // 如果resolved不為空,並且不是泛型參數
    if (resolved != null && !type.hasGenerics()) {
        // 雖然調用了這個方法,但是這個方法實際上調用的也是doGetBeanNamesForType
        return getBeanNamesForType(resolved, includeNonSingletons, includeNonSingletons);
    }
    else {
        return doGetBeanNamesForType(type, includeNonSingletons, includeNonSingletons);
    }
}

@Override
public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
    // 正常來講不會走這里,這里是什么情況??
    if (!isConfigurationFrozen() || type == null || !allowEagerInit) {
        return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);
    }
    // 先從緩存中找
    Map<Class<?>, String[]> cache =
            (includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);
    String[] resolvedBeanNames = cache.get(type);
    if (resolvedBeanNames != null) {
        return resolvedBeanNames;
    }
    // 緩存沒有,則創建,並放到緩存中
    resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
    if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {
        cache.put(type, resolvedBeanNames);
    }
    return resolvedBeanNames;
}

// NamedBeanHolder:持有beanName和beanInstance的包裝類
// BeanDefinitionHolder:包含名稱和別名以及bean定義的Holder。可以注冊為內部bean的占位符。
// 重點類:RootBeanDefinition、DefaultSingletonBeanRegistry
private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    List<String> result = new ArrayList<>();

    // 檢查全部的bean定義
    for (String beanName : this.beanDefinitionNames) {
        // 只有當bean名稱沒有定義為其他bean的別名時,才認為bean是合格的
        if (!isAlias(beanName)) {
            try {
                // 返回合並的RootBeanDefinition,如果指定的bean符合子bean定義,則遍歷父bean定義。【為什么要合並定義?后面會講】
                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 只有在bean定義完成時才檢查它。
                if (!mbd.isAbstract() && (allowEagerInit ||
                        (mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&
                                !requiresEagerInitForType(mbd.getFactoryBeanName()))) {
                    // 檢查給定的bean是否定義為FactoryBean。
                    boolean isFactoryBean = isFactoryBean(beanName, mbd);
                    // 返回由這個bean定義修飾的目標定義
                    BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
                    boolean matchFound = false;
                    // 允許FactoryBean初始化(allowEagerInit==true 或者 這個bean是單例bean)
                    boolean allowFactoryBeanInit = allowEagerInit || containsSingleton(beanName);
                    // 
                    boolean isNonLazyDecorated = dbd != null && !mbd.isLazyInit();
                    // 不是FactoryBean
                    if (!isFactoryBean) {
                        if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
                            // 檢查給定名稱的bean是否與指定的類型匹配。允許應用額外的約束,以確保不過早地創建bean。
                            // 注意這個isTypeMatch方法是@since 5.2新加的,內容過多,暫且不談
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    }
                    // 是FactoryBean
                    else  {
                        if (includeNonSingletons || isNonLazyDecorated ||
                                (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                        // 不匹配
                        if (!matchFound) {
                            // In case of FactoryBean, try to match FactoryBean instance itself next.
                            beanName = FACTORY_BEAN_PREFIX + beanName;
                            matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
                        }
                    }
                    // 只有匹配的才會記錄下來
                    if (matchFound) {
                        result.add(beanName);
                    }
                }
            }
            catch (CannotLoadBeanClassException | BeanDefinitionStoreException ex) {
                if (allowEagerInit) {
                    throw ex;
                }
                // Probably a placeholder: let's ignore it for type matching purposes.
                LogMessage message = (ex instanceof CannotLoadBeanClassException) ?
                        LogMessage.format("Ignoring bean class loading failure for bean '%s'", beanName) :
                        LogMessage.format("Ignoring unresolvable metadata in bean definition '%s'", beanName);
                logger.trace(message, ex);
                onSuppressedException(ex);
            }
        }
    }


    // 檢查手動注冊的單例。
    for (String beanName : this.manualSingletonNames) {
        try {
            // 對於FactoryBean,匹配FactoryBean創建的對象。【org.springframework.beans.factory.FactoryBean】(FactoryBean后面也會講)
            if (isFactoryBean(beanName)) {
                if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {
                    result.add(beanName);
                    // 已經匹配過這個bean,跳過
                    continue;
                }
                // 對於FactoryBean,接下來嘗試匹配FactoryBean本身。
                beanName = FACTORY_BEAN_PREFIX + beanName;
            }
            // 匹配原始bean實例(可能是原始的FactoryBean)。
            if (isTypeMatch(beanName, type)) {
                result.add(beanName);
            }
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Shouldn't happen - probably a result of circular reference resolution...
            logger.trace(LogMessage.format("Failed to check manually registered singleton with name '%s'", beanName), ex);
        }
    }

    return StringUtils.toStringArray(result);
}

這么多邏輯,無非作者考慮的很周全,實際上只是一個根據類型獲取bean名稱的過程。另外你還能發現Spring的命名特點,getXXX方法僅僅是做了一些准備工作,真正工作的是doGetXXX方法。

②:doGetBean方法

 這個方法比較復雜,涉及到其它的方法也很多,所以我在后面單獨一部分講解,麻煩移步后面。

③:獲取主要候選名稱

protected String determinePrimaryCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String primaryBeanName = null;
    // 遍歷候選名稱集合
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        // 如果是主要候選對象。這里返回bean定義里的primary對象的值,具體來說就是如果你定義bean的時候用@Primary注解標注的,則是true
        if (isPrimary(candidateBeanName, beanInstance)) {
            // 因為是循環所有的候選名稱,第一次primaryBeanName肯定是null,所以在else語句給它賦值。如果出現了多個Primary注解的bean,那就會拋出異常
            if (primaryBeanName != null) {
                boolean candidateLocal = containsBeanDefinition(candidateBeanName);
                boolean primaryLocal = containsBeanDefinition(primaryBeanName);
                if (candidateLocal && primaryLocal) {
                    throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                            "more than one 'primary' bean found among candidates: " + candidates.keySet());
                }
                else if (candidateLocal) {
                    primaryBeanName = candidateBeanName;
                }
            }
            else {
                primaryBeanName = candidateBeanName;
            }
        }
    }
    return primaryBeanName;
}

總結:如果出現了多個候選名稱,則會選出被@Primary注解標注的bean。如果出現多個@Primary的bean,依然會拋出異常。

④:獲取最高優先級名稱

protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
    String highestPriorityBeanName = null;
    Integer highestPriority = null;
    for (Map.Entry<String, Object> entry : candidates.entrySet()) {
        String candidateBeanName = entry.getKey();
        Object beanInstance = entry.getValue();
        if (beanInstance != null) {
            // 獲取優先級,通過Primary的例子,這個也可以猜出是標記了@Priority注解,數字越小優先級越高。
            // @Priority注解需要單獨引入依賴:

            // <dependency>
            //     <groupId>javax.annotation</groupId>
            //     <artifactId>javax.annotation-api</artifactId>
            //     <version>1.3.2</version>
            // </dependency>

            Integer candidatePriority = getPriority(beanInstance);
            if (candidatePriority != null) {
                if (highestPriorityBeanName != null) {
                    if (candidatePriority.equals(highestPriority)) {
                        throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
                                "Multiple beans found with the same priority ('" + highestPriority +
                                "') among candidates: " + candidates.keySet());
                    }
                    else if (candidatePriority < highestPriority) {
                        highestPriorityBeanName = candidateBeanName;
                        highestPriority = candidatePriority;
                    }
                }
                else {
                    highestPriorityBeanName = candidateBeanName;
                    highestPriority = candidatePriority;
                }
            }
        }
    }
    return highestPriorityBeanName;
}

 

主要方法調用流程

 

核心方法依然是org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

先看一下重點步驟,然后分步解釋

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 1. 轉換bean名稱
    final String beanName = transformedBeanName(name);
    Object bean;

    // 2. 檢查單例緩存中手動注冊的單例對象
    Object sharedInstance = getSingleton(beanName);
    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 + "'");
            }
        }
        // 3. 獲取給定bean實例的對象,可能是它本身,也可能是FactoryBean創建的對象。
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 如果指定的原型bean正在創建,則拋出異常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 獲取父工廠
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 當前工廠里不存在這個bean定義則在父工廠里面找
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 獲取原始bean名稱
            String nameToLookup = originalBeanName(name);
            // 下面都是遞歸尋找過程
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                        nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 不僅僅做類型檢查,還要創建,則要先記錄下來
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        // 下面就是創建的過程了

        try {
            // 4. 合並bean定義,拿到RootBeanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 檢查bean定義
            checkMergedBeanDefinition(mbd, beanName, args);

            // 保證當前bean所依賴的bean的初始化。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 5. 給當前bean注冊一個依賴bean
                    registerDependentBean(dep, beanName);
                    try {
                        // 遞歸實例化依賴
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 6. 創建單實例bean
            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);
            }

            // 7. 創建多實例bean
            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 {
                // 8. 在指定的scope上實例化bean
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        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);
                }
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 9. 檢查所需的類型是否與實際bean實例的類型相匹配。
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;
}

大概過程:

1. 轉換bean名稱。

2. 查看緩存中有沒有,有則直接返回。

3. 緩存沒有,先找到並確定bean定義。

4. 合並bean定義。

5. 檢查循環依賴。

6. 根據配置,創建單實例bean還是多實例bean還是scope范圍的bean。

7. 做最后的類型檢查,無誤后返回。

下面分步驟

1. 轉換bean名稱。

protected String transformedBeanName(String name) {
    // beanName轉換分兩部分,一個是去掉工廠的取消引用前綴;一個是將別名解析為規范名稱。
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

// 返回實際的bean名稱,去掉工廠的取消引用前綴(如果有,也去掉重復的工廠前綴)
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));   // 只要發現beanName以&開頭,就會去除&,所以你就算寫一百個&也不會有錯誤。
        return beanName;
    });
}

// 確定原始名稱,將別名解析為規范名稱。
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 根據傳入的名稱,從別名Map里查詢
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

這里涉及兩個擴展內容,第一個就是FactoryBean,第二個就是別名。

BeanFactory和FactoryBean?

BeanFactory是頂級接口,是IDC容器實現的基礎。

FactoryBean是為用戶准備的,用來實例化一些復雜的Bean,給上層應用帶來便利。

來看個例子,重新修改配置類的內容,加入了一個FactoryBean,以及定義了別名。

import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BookConfig {

    @Bean(name = {"第一個是原始名稱", "book", "tom", "cat"})
    public BookFactoryBean book(){
        BookFactoryBean bookFactoryBean = new BookFactoryBean();
        bookFactoryBean.setBeanInfo("它們隱藏了實例化一些復雜bean 的細節,給上層應用帶來了便利");
        return bookFactoryBean;
    }
    
}

class BookFactoryBean implements FactoryBean<Book>{

    private String beanInfo;

    @Override
    public Book getObject() throws Exception {
        return new Book("AAA");
    }

    @Override
    public Class<?> getObjectType() {
        return Book.class;
    }

    public String getBeanInfo() {
        return beanInfo;
    }

    public void setBeanInfo(String beanInfo) {
        this.beanInfo = beanInfo;
    }
}

運行程序代碼

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new AnnotationConfigApplicationContext(BookConfig.class);
//        Book book = context.getBean(Book.class);
        Object bean = context.getBean("&&&book");
        Object bean1 = context.getBean("第一個是原始名稱");
        Object bean2 = context.getBean("cat");
        System.out.println(bean);
        System.out.println(bean1);
        System.out.println(bean2);
    }

}

輸出結果:

第一個問題:beanName前面加個&,代表獲取FactoryBean。

第二個問題:無論用什么名稱,在內部都會找到它的原始名稱。

根據debug的結果可以看出:定位bean還是需要原始名稱,如果傳入的是原始名稱,則直接返回。

總結:

轉換beanName包含兩部分:一個是去掉工廠的&前綴,另一個是利用AliasMap找到Bean的原始名稱。

2. 檢查單例緩存

這個方法在另一個類里:DefaultSingletonBeanRegistry#getSingleton(java.lang.String)

public Object getSingleton(String beanName) {
    // allowEarlyReference 為true
    return getSingleton(beanName, true);
}

// 根據名稱找到注冊的(原始)單例對象。
// 檢查已經實例化的單例並允許對當前單例的早期引用(解析循環引用)。
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 這里獲得的可能是bean也可能是FactoryBean
    Object singletonObject = this.singletonObjects.get(beanName);
    // 如果沒有獲取到並且發現當前bean正在創建
    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);
                    // 移除工廠緩存中的bean
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    // 只要獲取到,即返回
    return singletonObject;
}

這其中涉及了三個緩存

/** 單例對象緩存: beanName -> beanInstance. 存放創建完成的bean */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

/** 單例工廠緩存: beanName -> ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

/** 早期單例對象緩存: beanName -> beanInstance. 已經實例化但是還沒有創建完成的單例bean被放到這里面,其目的是用來檢測循環引用 */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

/** 已經注冊的bean放在這里. */
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);


獲取過程很簡單:先去緩存中尋找,緩存中沒有去早期緩存中找,早期緩存沒有則獲取單例工廠,利用工廠方法獲取實例,並添加到早期緩存中,同時移除工廠緩存中的bean。最后返回。

對於Spring解決循環依賴的問題:

Spring只能解決單例模式下的Setter循環依賴,Spring不能解決prototype作用域的bean之間的循環依賴。
Spring在獲取ClassA的實例時,不等ClassA完成創建就將其曝光加入正在創建的bean緩存中。
在解析ClassA的屬性時,又發現依賴於ClassB,再次去獲取ClassB,當解析ClassB的屬性時,又發現需要ClassA的屬性,
但此時的ClassA已經被提前曝光加入了正在創建的bean的緩存中,則無需創建新的的ClassA的實例,直接從緩存中獲取即可。從而解決循環依賴問題。

另外:根據代碼邏輯不難發現,ClassA實例化的時候發現需要依賴ClassB,於是把ClassA先緩存起來,去實例化ClassB。也就是說,優先初始化最底層對象

根據Debug的結果,這一步可能獲取到的是個FactoryBean:

3. 獲取真正實例對象getObjectForBeanInstance

因為上一步的過程,我們可以知道,返回結果不一定是我們需要的對象。

/**
 * org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getObjectForBeanInstance
 * 
 * @since 5.0
 * @see #obtainFromSupplier
 */
@Override
protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    // 獲取當前ThreadLocal存儲的變量,也就是當前正在創建的bean
    String currentlyCreatedBean = this.currentlyCreatedBean.get();
    if (currentlyCreatedBean != null) {
        // 如果當前有正在創建的bean,則注冊為beanName所依賴的bean
        registerDependentBean(beanName, currentlyCreatedBean);
    }
    return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
}

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());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        // 返回FactoryBean實例
        return beanInstance;
    }
    // 走到這里,證明我們需要的是bean實例,而不是FactoryBean實例。而到這里beanInstance可能是個bean,也可能是個FactoryBean。
    // 如果它是一個FactoryBean,我們將使用它來創建一個bean實例
    if (!(beanInstance instanceof FactoryBean)) {
        // 不是FactoryBean,直接返回即可。
        return beanInstance;
    }
    Object object = null;
    if (mbd != null) {
        mbd.isFactoryBean = true;
    }
    else {
        // 根據beanName,從FactoryBean緩存中獲取FactoryBean
        object = getCachedObjectForFactoryBean(beanName);
    }
    // FactoryBean緩存中沒找到目標
    if (object == null) {
        // 把當前的beanInstance強制轉換成FactoryBean
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // RootBeanDefinition為空並且beanDefinitionMap中包含次beanName
        if (mbd == null && containsBeanDefinition(beanName)) {
            // 合並bean定義,返回一個RootBeanDefinition
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 代表RootBeanDefinition是否是合成得到的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 從FactoryBean中獲取bean實例
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

這部分的主要邏輯是:

1. 根據name判斷我們需要的是個Bean實例還是FactoryBean實例。

2. 如果需要FactoryBean實例,則做一些校驗后返回上一步得到的對象。

2. 如果需要Bean實例,則判斷上一步返回的對象是不是個純粹的Bean,是則返回;如果是個FactoryBean實例,則用FactoryBean創建一個Bean實例返回。

這部分涉及一個從FactoryBean中獲取bean實例的過程:

// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // 是單例並且單例緩存中有此beanName的key
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            // 先檢查緩存,這個factoryBeanObjectCache存儲的是由FactoryBean創建的單例對象的緩存。key為FactoryBean名稱。
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // factoryBeanObjectCache緩存沒有,則執行FactoryBean的getObject方法,獲取bean實例
                object = doGetObjectFromFactoryBean(factory, beanName);
                // 考慮循環依賴的情況
                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;
                        }
                        // 單例創建之前,將單例對象注冊為當前正在創建的狀態(添加到singletonsCurrentlyInCreation里)
                        beforeSingletonCreation(beanName);
                        try {
                            // 在初始化之后應用后置處理
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            // 最后將單例對象正在創建的狀態移除(從singletonsCurrentlyInCreation里移除)
                            afterSingletonCreation(beanName);
                        }
                    }
                    // 因為是FactoryBean創建的bean,所以添加到對應的緩存里
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            // // 返回結果
            return object;
        }
    }
    // 不是單例或者緩存中沒有此beanName
    else {
        // 調用factory的getObject方法獲取實例bean
        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;
    }
}

簡單來講:

1. 先從factoryBeanObjectCache緩存中查看是否存在此FactoryBean創建的單例,有則返回,沒有的話執行FactoryBean的getObject方法來獲取;

2. 獲取完進行后置處理,后置處理之前將次beanName添加到 singletonsCurrentlyInCreation 集合中以示正在創建中,后置處理之后將beanName從 singletonsCurrentlyInCreation 集合中移除,以清除正在創建狀態。

4. 這部分涉及了一個合並BeanDefinition的過程。關於BeanDefinition的結構如下:

-

待續

5. 注冊依賴Bean

/** 別人依賴我:key=我,value=依賴我的人 */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** 我依賴別人:key=我,value=我依賴的人 */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

// beanName依賴dep
registerDependentBean(dep, beanName);

// beanName-被依賴者;dependentBeanName-依賴者
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);
    // 別人依賴我:key=beanName,value=Set(dependentBeanName)
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }
    // 我依賴別人:key=dependentBeanName,value=Set(beanName)
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}

這個依賴關系有點繞,要仔細一點捋一下。

dependentBeanMap:dependent【依賴】Bean【我】Map,key是被依賴者,value是依賴者
dependenciesForBeanMap:dependencies【依賴項】For【給】Bean【我】Map,key是依賴者,value是被依賴者

不知道我這樣解釋能不能明白這個關系?

6. 創建單實例bean

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;

    // 確保此時bean已經解析,並在動態解析的類不能存儲在共享的合並bean定義中時,克隆bean定義。【根據Bean定義解析BeanClass】
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    try {
        // 驗證&准備在該bean中定義的覆蓋的方法。
        // 檢查是否存在具有指定名稱的方法。
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // 給 Bean后置處理器 一個機會,返回一個目標bean實例的代理
        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 {
        // 【執行創建bean的具體邏輯】
        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. 解析BeanClass

2. 驗證&准備Bean定義中覆蓋的方法

3. 執行創建Bean

來看doCreateBean

// 【執行創建bean的具體邏輯】
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
        throws BeanCreationException {

    // BeanWrapper是個Bean包裝類
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // ☆☆☆【實例化Bean】
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final 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 (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Post-processing of merged bean definition failed", ex);
            }
            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.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // ☆☆☆【屬性賦值】
        populateBean(beanName, mbd, instanceWrapper);
        // ☆☆☆【初始化Bean實例】
        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);
        }
    }

    // 如果是提前暴露單例
    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);
                    }
                }
                if (!actualDependentBeans.isEmpty()) {
                    throw new BeanCurrentlyInCreationException(beanName,
                            "Bean with name '" + beanName + "' has been injected into other beans [" +
                            StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                            "] in its raw version as part of a circular reference, but has eventually been " +
                            "wrapped. This means that said other beans do not use the final version of the " +
                            "bean. This is often the result of over-eager type matching - consider using " +
                            "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
                }
            }
        }
    }

    // 將bean注冊為一次性的
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

這部分同樣也主要分為三步,同時這也是Bean生命周期的體現

1. ☆☆☆【實例化Bean】

2. ☆☆☆【屬性賦值】

3. ☆☆☆【初始化Bean實例】

4. ☆☆☆【銷毀】(銷毀在這里沒有體現)

☆☆☆【實例化Bean】☆☆☆

// 通過適當的策略實例化Bean:工廠方法、構造方法自動裝配或者簡單實例化
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    // 獲取創建bean實例的回調
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        // 利用instanceSupplier獲取一個Bean實例
        return obtainFromSupplier(instanceSupplier, beanName);
    }
    // 如果工廠方法不為空
    if (mbd.getFactoryMethodName() != null) {
        // 通過工廠方法實例化Bean(詳見:org.springframework.beans.factory.support.ConstructorResolver#instantiateUsingFactoryMethod)
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    // 如果已解析
    if (resolved) {
        // 如果自動裝配
        if (autowireNecessary) {
            // 構造方法自動裝配(詳見:org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor)
            return autowireConstructor(beanName, mbd, null, null);
        }
        // 否則是普通的實例化
        else {
            return instantiateBean(beanName, mbd);
        }
    }
    // 返回用於給定bean的候選構造函數,檢查所有已注冊的構造函數
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
            mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        // 構造方法自動裝配(詳見:org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor)
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    // 如果有默認的構造函數
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // 沒有特殊的處理器,使用無參構造函數
    return instantiateBean(beanName, mbd);
}

這個方法主要是選取適當的策略來決定如何創建Bean

1. 利用Bean定義中的instanceSupplier獲取Bean

2. 利用指定的工廠方法名稱實例化Bean

3. 利用構造方法自動裝配實例化Bean

4. 簡單的使用無參構造函數實例化Bean,這個也是默認的處理方式

選擇默認處理方式:

protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
    try {
        Object beanInstance;
        final BeanFactory parent = this;
        if (System.getSecurityManager() != null) {
            beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                    getInstantiationStrategy().instantiate(mbd, beanName, parent),
                    getAccessControlContext());
        }
        else {
            // org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory)
            beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
        }
        // 新建一個Bean包裝類
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        // 初始化Bean包裝類
        initBeanWrapper(bw);
        return bw;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
    }
}

這個方法描述了兩個主要步驟

1. 實例化Bean

2. 新建 & 初始化包裝類,並返回。

看實例化

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
    // 如果沒有覆蓋的方法,則不使用CGLIB覆蓋
    if (!bd.hasMethodOverrides()) {
        Constructor<?> constructorToUse;
        synchronized (bd.constructorArgumentLock) {
            constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
            if (constructorToUse == null) {
                // 獲取Class對象
                final Class<?> clazz = bd.getBeanClass();
                if (clazz.isInterface()) {
                    throw new BeanInstantiationException(clazz, "Specified class is an interface");
                }
                try {
                    if (System.getSecurityManager() != null) {
                        constructorToUse = AccessController.doPrivileged(
                                (PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
                    }
                    else {
                        // 獲取Constructor對象
                        constructorToUse = clazz.getDeclaredConstructor();
                    }
                    // 給RootBeanDefinition設置已解析的構造函數或工廠方法
                    bd.resolvedConstructorOrFactoryMethod = constructorToUse;
                }
                catch (Throwable ex) {
                    throw new BeanInstantiationException(clazz, "No default constructor found", ex);
                }
            }
        }
        // 工具類,實例化Bean(繞了這么多,真正干活的是這個方法)
        return BeanUtils.instantiateClass(constructorToUse);
    }
    else {
        // Must generate CGLIB subclass.
        // 子類可以覆蓋這個方法,如果子類可以用給定的RootBeanDefinition中指定的方法注入實例化一個對象。實現該方法的目的是拋出UnsupportedOperationException。
        // 實例化應該使用無參數的構造函數。
        return instantiateWithMethodInjection(bd, beanName, owner);
    }
}

public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
    Assert.notNull(ctor, "Constructor must not be null");
    try {
        // 反射方法(ctor.setAccessible(true);)
        ReflectionUtils.makeAccessible(ctor);
        if (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass())) {
            return KotlinDelegate.instantiateClass(ctor, args);
        }
        else {
            // 獲得參數類型
            Class<?>[] parameterTypes = ctor.getParameterTypes();
            // 參數數量校驗
            Assert.isTrue(args.length <= parameterTypes.length, "Can't specify more arguments than constructor parameters");
            Object[] argsWithDefaultValues = new Object[args.length];
            // 組裝參數
            for (int i = 0 ; i < args.length; i++) {
                if (args[i] == null) {
                    Class<?> parameterType = parameterTypes[i];
                    argsWithDefaultValues[i] = (parameterType.isPrimitive() ? DEFAULT_TYPE_VALUES.get(parameterType) : null);
                }
                else {
                    argsWithDefaultValues[i] = args[i];
                }
            }
            // 反射方法,利用給定的參數new一個實例
            return ctor.newInstance(argsWithDefaultValues);
        }
    }
    catch (InstantiationException ex) {
        throw new BeanInstantiationException(ctor, "Is it an abstract class?", ex);
    }
    catch (IllegalAccessException ex) {
        throw new BeanInstantiationException(ctor, "Is the constructor accessible?", ex);
    }
    catch (IllegalArgumentException ex) {
        throw new BeanInstantiationException(ctor, "Illegal arguments for constructor", ex);
    }
    catch (InvocationTargetException ex) {
        throw new BeanInstantiationException(ctor, "Constructor threw exception", ex.getTargetException());
    }
}

實際上實例化的方法並不復雜,復雜的是前期准備的過程

實例化的過程:組裝參數成一個Object數組(無參的話數組長度為0),傳入Constructor的newInstance方法完成實例化。

實例化全程總結:

1. 根據情況選取合適的創建策略

  ☆ 利用Bean定義中的instanceSupplier獲取Bean

  ☆ 利用指定的工廠方法名稱實例化Bean

  ☆ 利用構造方法自動裝配實例化Bean

  ☆ 簡單的使用無參構造函數實例化Bean,這個也是默認的處理方式

2. 將實例封裝成一個包裝類

  ☆ 通過反射方法實例化Bean

  ☆ 新建 & 初始化Bean的包裝類

 

另外:我看了下利用工廠方法創建和構造方法自動裝配兩種方式,除了過程比較復雜,其實例化的時候調用的都是org.springframework.beans.factory.support.ConstructorResolver#instantiate(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object, java.lang.reflect.Method, java.lang.Object[])

進而調用org.springframework.beans.factory.support.SimpleInstantiationStrategy#instantiate(org.springframework.beans.factory.support.RootBeanDefinition, java.lang.String, org.springframework.beans.factory.BeanFactory, java.lang.Object, java.lang.reflect.Method, java.lang.Object...)

剛好和上面對上,實例化都是利用反射(當然這樣說也不是很嚴謹),因為實例化策略的實現有兩個,除了反射還有CGLIB,如圖:

 

☆☆☆【屬性賦值】☆☆☆

// ☆☆☆【屬性賦值】
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    // Bean實例為空的不用屬性賦值
    if (bw == null) {
        if (mbd.hasPropertyValues()) {
            throw new BeanCreationException(
                    mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
        }
        else {
            // Skip property population phase for null instance.
            return;
        }
    }

    // 給任何一個InstantiationAwareBeanPostProcessor在屬性設置之前修改bean狀態的機會。
    boolean continueWithPropertyPopulation = true;

    // 如果Bean定義不是合成的,並且,當前的工廠持有InstantiationAwareBeanPostProcessor列表
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 遍歷用於此工廠創建bean的beanpostprocessor列表
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // 如果當前Processor是InstantiationAwareBeanPostProcessor的子類實現
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 如果不是實例化之后的處理器,則設置continueWithPropertyPopulation為false,目的不再執行后續屬性設置
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    continueWithPropertyPopulation = false;
                    break;
                }
            }
        }
    }
    // 注:InstantiationAwareBeanPostProcessor出現在Bean實例化前后,屬性(自動裝配)之前。

    // 根據上面的執行結果,決定是否還要繼續
    if (!continueWithPropertyPopulation) {
        return;
    }

    // 嘗試獲取Bean定義里的屬性值映射列表
    PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

    // 獲取解析到的自動裝配模式
    int resolvedAutowireMode = mbd.getResolvedAutowireMode();
    // 如果是根據名稱自動裝配或者根據類型自動裝配,這里僅僅是將屬性名稱-屬性值的映射關系裝配到PropertyValues對象中
    if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
        MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
        // Add property values based on autowire by name if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
            autowireByName(beanName, mbd, bw, newPvs);
        }
        // Add property values based on autowire by type if applicable.
        if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
            autowireByType(beanName, mbd, bw, newPvs);
        }
        pvs = newPvs;
    }

    // 當前的工廠是否持有InstantiationAwareBeanPostProcessor列表
    boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
    // 是否需要檢查依賴
    boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

    PropertyDescriptor[] filteredPds = null;
    // 如果當前的工廠持有InstantiationAwareBeanPostProcessor列表
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        // 遍歷執行處理器,對屬性進行后置處理
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    if (filteredPds == null) {
                        filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                    }
                    pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }
    // 需要檢查依賴
    if (needsDepCheck) {
        if (filteredPds == null) {
            filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
        }
        // 檢查依賴
        checkDependencies(beanName, mbd, filteredPds, pvs);
    }

    // 最后,如果屬性值列表不為空
    if (pvs != null) {
        // 設置屬性
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}

大概流程是

1. 進行Bean實例化之后的后置處理。

2. 先獲取默認的屬性映射關系對象,然后根據模式判斷按照名稱還是按照類型自動裝配。

3. 遍歷后置處理器,對裝配好的屬性映射關系對象進行后置處理。

4. 檢查依賴。

5. 屬性賦值。

另:autowireByName/autowireByType/applyPropertyValues這三個方法暫時不提,太多了。

 

☆☆☆【初始化Bean實例】☆☆☆

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

// ☆☆☆【初始化Bean實例】
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 1. 執行Aware子類相關的方法
        invokeAwareMethods(beanName, bean);
    }
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 2. 初始化之前的后置處理
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
        // 3. 執行初始化方法
        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()) {
        // 4. 初始化之后的后置處理
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
}

1. Aware的子類

private void invokeAwareMethods(final String beanName, final Object bean) {
    // Aware是個頂級標記接口,作用是能夠感知自己的一些屬性。示例在后面單獨說明。
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

2、3 . 初始化前后的處理

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
        throws BeansException {
    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 遍歷后置處理器,調用初始化之前的后置處理方法
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
@Override
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;
}

4. 初始化方法

// 初始化
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        throws Throwable {
    boolean isInitializingBean = (bean instanceof InitializingBean);
    // 這個Bean實現了InitializingBean接口
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
            logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
                    ((InitializingBean) bean).afterPropertiesSet();
                    return null;
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            // 因為InitializingBean接口里只有一個afterPropertiesSet方法,所以這個是由子類實現的方法。
            // 作用顧名思義,在屬性賦值之后做的一些善后工作。該方法允許bean實例在設置了所有bean屬性后執行總體配置驗證和最終初始化。
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
    // 如果配置了比如:@Bean(initMethod = "myInit"),指定了自定義的初始化方法,就會在這個時候執行
    if (mbd != null && bean.getClass() != NullBean.class) {
        // 獲取初始化方法名稱
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
                !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 這里內部實現是利用反射執行初始化方法的
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

示例

定義一個Bean

import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;

@Getter
@Setter
public class Apple implements BeanNameAware,InitializingBean {

    private String id;
    private String name;

    // 對於Aware接口的子類,實現了的方法會在Bean的初始化階段被調用
    public void setBeanName(String name) {
        this.id = name;
    }

    // 對於實現InitializingBean接口的Bean,需要實現這個方法,目的是屬性賦值之后做的一些善后工作
    public void afterPropertiesSet() throws Exception {
        System.out.println("Do Anything");
        this.name = "我這里設置了屬性B";
    }

    // 自定義的Bean初始化方法
    public void myInitMethod(){
        System.out.println("Do Something");
    }
}

配置類

import com.entity.Apple;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {

    @Bean(initMethod = "myInitMethod")
    public Apple apple(){
        Apple apple = new Apple();
        apple.setName("我這里設置了屬性A");
        return apple;
    }
}

運行

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {

    public static void main(String[] args){
        ApplicationContext app = new AnnotationConfigApplicationContext(Config.class);
    }
}

如果你打斷點,你會在這里攔截到我們配置影響的第一個點【Aware接口

進入方法,會執行我們定義的setBeanName方法(這樣,我們實現了BeanNameAware接口的Bean就能獲取到自己的Bean名稱

----------------

接下來到第二個部分(InitializingBean接口

進入方法,先執行我們定義的  afterPropertiesSet

----------

然后到第三部分,執行我們定義的自定義初始化方法。

 

初始化部分總結:

1. 如果Bean實現了Aware接口,則會執行其中的方法(方法只有一個)。實際應用比如:寫一個實現ApplicationContextAware接口的工具類,來獲取當前應用程序上下文。進而手動getBean。

2. 執行初始化之前的后置處理器。

3. 初始化:① 如果Bean實現了 InitializingBean 接口,則會執行 afterPropertiesSet。 ② 如果Bean指定了自定義的初始化方法,則會執行此方法。

4. 執行初始化之后的后置處理器。

思考:如果只是一個普通的Bean,則不會執行這么多邏輯。這些額外的處理都是為了應付一些復雜的場景,這里也能體會到作者的用意——擴展性。

 

☆☆☆【總結:Bean實例化過程,主要過程全部體現在AbstractAutowireCapableBeanFactory類里】☆☆☆

☆☆☆【銷毀Bean】☆☆☆

如果前面創建單例出現了異常,就會執行銷毀操作。

if (mbd.isSingleton()) {
    sharedInstance = getSingleton(beanName, () -> {
        try {
            return createBean(beanName, mbd, args);
        }
        catch (BeansException ex) {
            // 顯式地從單例緩存中刪除實例:它可能被創建過程提前暴露放在那里,以允許循環引用解析。
            // 還要刪除所有接受該bean臨時引用的bean。
            destroySingleton(beanName);
            throw ex;
        }
    });
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

如果你想打斷點到這一行,只需要在Apple實體類里加一句話:

 

打斷點能捕獲到

 

 

// 先執行:org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingleton
public void destroySingleton(String beanName) {
    // 執行父類的邏輯
    super.destroySingleton(beanName);
    // 更新manualSingletonNames集合,從中刪除beanName
    removeManualSingletonName(beanName);
    // 清除所有按照Type獲取的BeanName緩存【this.allBeanNamesByType.clear(); this.singletonBeanNamesByType.clear();】
    clearByTypeCache();
}

父類邏輯

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton
public void destroySingleton(String beanName) {
    // 刪除所有此beanName注冊的Bean緩存(singletonObjects、singletonFactories、earlySingletonObjects、registeredSingletons)
    removeSingleton(beanName);
    // 銷毀相應的DisposableBean實例
    DisposableBean disposableBean;
    synchronized (this.disposableBeans) {
        // 從存儲一次性Bean的LinkedHashMap集合中刪除此beanName
        disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
    }
    // 執行刪除
    destroyBean(beanName, disposableBean);
}

destroyBean

protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    // Trigger destruction of dependent beans first...
    Set<String> dependencies;
    synchronized (this.dependentBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        // 從依賴Map中移除並獲取依賴此bean的集合
        dependencies = this.dependentBeanMap.remove(beanName);
    }
    if (dependencies != null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
        }
        // 如果存在依賴,則遞歸刪除所有依賴這個beanName的所有bean
        // 這個地方白話解釋一下:母貓死亡(發生了異常),那么母貓影響的是所有依賴母貓的小貓(Bean)
        for (String dependentBeanName : dependencies) {
            destroySingleton(dependentBeanName);
        }
    }

    // Actually destroy the bean now...
    // 刪除一次性的bean
    if (bean != null) {
        try {
            bean.destroy();
        }
        catch (Throwable ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Destruction of bean with name '" + beanName + "' threw an exception", ex);
            }
        }
    }

    // 銷毀當前Bean所包含的bean
    Set<String> containedBeans;
    synchronized (this.containedBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        containedBeans = this.containedBeanMap.remove(beanName);
    }
    
    if (containedBeans != null) {
        // 如果包含其它bean,則遞歸刪除
        // 這個地方白話解釋一下:母貓死亡(發生了異常),母貓所包含的所以東西比如粑粑(Bean),都要回歸大自然。
        for (String containedBeanName : containedBeans) {
            destroySingleton(containedBeanName);
        }
    }

    // 從其他bean的依賴項中移除被破壞的bean。這里是看一下dependentBeanMap中余下的value里是否含有當前beanName
    synchronized (this.dependentBeanMap) {
        for (Iterator<Map.Entry<String, Set<String>>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
            Map.Entry<String, Set<String>> entry = it.next();
            Set<String> dependenciesToClean = entry.getValue();
            dependenciesToClean.remove(beanName);
            if (dependenciesToClean.isEmpty()) {
                it.remove();
            }
        }
    }

    // 刪除bean准備好的依賴項信息。
    this.dependenciesForBeanMap.remove(beanName);
}

 

主要的銷毀包含:

1. 銷毀所有直接依賴此bean的bean(遞歸刪除)

2. 如果存在的話,刪除一次性注冊的bean

3. 銷毀此bean包含的所有bean(遞歸刪除)

4. 遍歷dependentBeanMap的value,看是否存在此bean

5. 刪除自己已准備好的依賴項信息

這里涉及三個集合

/** 我擁有的人:key=我,value=我擁有的人 */
private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);
/** 別人依賴我:key=我,value=依賴我的人 */
private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
/** 我依賴別人:key=我,value=我依賴的人 */
private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

圖解一下

7. 創建多實例bean

// 原型模式
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);
}

protected void beforePrototypeCreation(String beanName) {
    // prototypesCurrentlyInCreation是一個本地線程變量,存儲當前正在創建的多實例Bean
    Object curVal = this.prototypesCurrentlyInCreation.get();
    if (curVal == null) {
        // 如果當前線程沒有創建任務,則設置為當前BeanName
        this.prototypesCurrentlyInCreation.set(beanName);
    }
    else if (curVal instanceof String) {
        // 如果當前存儲的變量是String類型,則新建一個Set集合,存儲這個String變量以及我們將要創建的beanName
        Set<String> beanNameSet = new HashSet<>(2);
        beanNameSet.add((String) curVal);
        beanNameSet.add(beanName);
        // 存儲進線程本地變量
        this.prototypesCurrentlyInCreation.set(beanNameSet);
    }
    else {
        Set<String> beanNameSet = (Set<String>) curVal;
        // 轉換成Set集合,然后把當前beanName添加進去
        beanNameSet.add(beanName);
    }
}
protected void afterPrototypeCreation(String beanName) {
    // 獲取線程本地變量
    Object curVal = this.prototypesCurrentlyInCreation.get();
    // 如果是String類型,直接移除
    if (curVal instanceof String) {
        this.prototypesCurrentlyInCreation.remove();
    }
    else if (curVal instanceof Set) {
        // 如果是Set集合,先移除Set集合中的beanName
        Set<String> beanNameSet = (Set<String>) curVal;
        beanNameSet.remove(beanName);
        // 如果集合為空,才去移除線程本地變量
        if (beanNameSet.isEmpty()) {
            this.prototypesCurrentlyInCreation.remove();
        }
    }
}

與單例模式不同的是創建前后有個處理的過程,看過程

1. 創建之前(目的是把任務[beanName]放進本地線程變量中)

  線程本地變量獲取為空,則直接設置成當前beanName。

  獲取到線程本地變量,並且類型為String,則新建一個Set集合,將新老變量添加到集合中,最后設置成線程本地變量。

  獲取到線程本地變量,類型是Set集合,則先做類型轉換,然后添加當前的beanName到集合中,最后設置成線程本地變量。

2. 創建Bean,在doCreateBean方法中有這么一行,如下:

  boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));

  目的是用來檢測循環依賴,添加到相應的緩存中,同時它是僅僅針對單例Bean。而多實例Bean的創建不會有這個過程的。

3. 創建之后(目的是把任務[beanName]從本地線程變量中移除)

  如果獲取到的變量是String類型,證明只有這一個任務,直接執行remove即可。

  如果獲取到的變量類型是Set集合類型,證明不止當前一個任務,要把當前任務從Set集合中刪除;然后再判斷Set集合是否為空,為空才會執行remove方法。

 

8. 在指定的scope(作用域)上實例化bean

這里呢,與前面兩種不同的地方僅僅是多了個獲取Scope的過程,其他部分都不是事。

-

☆ 擴展——IOC容器的關閉

不賣關子直接上,Java應用程序里可以添加關閉鈎子。

public static void main(String[] args){
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        System.out.println("關閉之前我要優雅的處理資源");
    }));
}

這樣,當以下情況會觸發

1. 程序正常退出
2. 使用System.exit()
3. 終端Ctrl+C
4. 系統關閉
5. Kill pid命令干掉進程(不是kill -9 pid)

同樣,在Spring里也是這樣做的(org.springframework.context.support.AbstractApplicationContext#registerShutdownHook)

public void registerShutdownHook() {
    if (this.shutdownHook == null) {
        this.shutdownHook = new Thread("SpringContextShutdownHook") {
            public void run() {
                synchronized(AbstractApplicationContext.this.startupShutdownMonitor) {
                    AbstractApplicationContext.this.doClose();
                }
            }
        };
        Runtime.getRuntime().addShutdownHook(this.shutdownHook);
    }
}
/** @deprecated */
@Deprecated
public void destroy() {
    this.close();
}
public void close() {
    Object var1 = this.startupShutdownMonitor;
    synchronized(this.startupShutdownMonitor) {
        this.doClose();
        if (this.shutdownHook != null) {
            try {
                Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
            } catch (IllegalStateException var4) {
                ;
            }
        }
    }
}

當然Spring已經寫好了,不用我們去管。但是我們遇到一些業務場景可能會用到,現有框架比如Dubbo,聽說就是利用這個東西實現優雅停機的。

總結

實際上Spring的重點可以說有兩部分

1. 容器(IOC)創建過程:

ApplicationContext app = new AnnotationConfigApplicationContext(Config.class);

2. Bean加載過程(也可以說是Bean的實例化過程):

app.getBean("user");

這兩部分並不是井水不犯河水,因為容器創建過程,就涉及到單實例Bean的初始化過程了。

如果作用域是 Singleton,那么在容器創建的時候就會初始化,后面你getBean會直接返回緩存中的實例,生命周期交給容器處理。

如果作用域是 Prototype,那么每次調用getBean都會創建一個新的實例,生命周期交給調用者。

另外你還能發現,在Bean的實例化過程遇到的問題很多都是面試問的問題。比如:

BeanFactory和FactoryBean的區別?

Spring如何解決循環依賴的?

Bean的生命周期?等等

 

由於這部分內容比較多且復雜,一部分是年前寫的,一部分是在老家寫的,用的測試代碼可能不一樣,但是不影響Spring代碼的思路。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM