Spring中Bean注入原始碼分析

語言: CN / TW / HK

theme: smartblue

BeanDefinition和Bean

在Spring中Bean的注入涉及兩部分:

  1. BeanDefinition
  2. Bean

兩個物件存在先後順序,先注入BeanDefinition之後才執行Bean物件的注入。

那麼兩者有什麼關聯呢?

BeanDefinition和Bean的關係:可以理解為BeanDefinition是Bean的包裝類,類似Java中類和屬性的關係。

BeanDefinition是對Bean物件的包裝,BeanDefinition中封裝了Bean相關的描述,比如bean物件,bean的單例還是原型、bean的父級、懶載入方式等等。

```java public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

void setScope(@Nullable String scope);

@Nullable
String getScope();

void setLazyInit(boolean lazyInit);

boolean isLazyInit();

}

//bean的原資料 public interface BeanMetadataElement { @Nullable Object getSource(); } ```

在BeanDefinition中繼承了BeanMetadataElement,該類是Bean的原資料,該類中例項化了Bean物件為Object。因此在BeanDefinition中呼叫getSource就可以獲取到Bean物件。

分清楚BeanDefinition和Bean之後再看BeanDefinition的注入,因為只有注入了BeanDefinition才會注入後續的Bean。

BeanDefinition的注入

BeanDefinitionRegistry介面

BeanDefinitin的注入通過介面BeanDefinitionRegistry抽象了各種對BeanDefinition的操作,例如

  • BeanDefinitionRegistry#registerBeanDefinition(注入到beanDefinition中)
  • BeanDefinitionRegistry#removeBeanDefinition(從beanDefinition容器中移除)
  • BeanDefinitionRegistry#getBeanDefinition(獲取BeanDefinition)

```java public interface BeanDefinitionRegistry extends AliasRegistry {

void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException;

void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

boolean containsBeanDefinition(String beanName);

String[] getBeanDefinitionNames();

int getBeanDefinitionCount();

boolean isBeanNameInUse(String beanName);

} ```

該介面是操作BeanDefinition的基礎介面,該類是一個介面型別並不是一個抽象類,因此該介面中不會定義任何BeanDefinition的容器,BeanDefinition的容器只在各實現類中定義並使用。任何需要操作BeanDefinition的實現都需要實現該介面。

BeanDefinitionRegistry的實現類

找到操作BeanDefinition的介面就可以通過介面檢視介面的實現類,進而找到BeanDefinition的應用。

BeanDefinition常見的幾個實現類有:

  • DefaultListableBeanFactory
  • SimpleBeanDefinitionRegistry

SimpleBeanDefinitionRegistry

```java public class SimpleBeanDefinitionRegistry extends SimpleAliasRegistry implements BeanDefinitionRegistry {

/**beanDefinition的容器,通過ConcurrentHashMap實現. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(64);


//該類的實現方法只是實現了最簡單的beanDefinition的注入,在Java開發環境中並不會使用該實現類
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
        throws BeanDefinitionStoreException {

    Assert.hasText(beanName, "'beanName' must not be empty");
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    this.beanDefinitionMap.put(beanName, beanDefinition);
}

} ```

該實現類中只做了最簡單的注入功能,沒有任何的邏輯處理,因此在實際開發過程中Spring並不會使用該類。

DefaultListableBeanFactory

```java public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {

    //beanDefinition的容器
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);



    //向BeanFactory中注入BeanDefinition
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {

        Assert.hasText(beanName, "Bean name must not be empty");
        Assert.notNull(beanDefinition, "BeanDefinition must not be null");

        if (beanDefinition instanceof AbstractBeanDefinition) {
            try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }
            catch (BeanDefinitionValidationException ex) {
                throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
                        "Validation of bean definition failed", ex);
            }
        }

        BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
        //判斷beanDefinition容器中是否已存在該beanDefinition
        if (existingDefinition != null) {
            //是否可以覆蓋
            if (!isAllowBeanDefinitionOverriding()) {
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            } else if (existingDefinition.getRole() < beanDefinition.getRole()) {
                // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
                if (logger.isInfoEnabled()) {
                    logger.info("Overriding user-defined bean definition for bean '" + beanName +
                            "' with a framework-generated bean definition: replacing [" +
                            existingDefinition + "] with [" + beanDefinition + "]");
                }
            } else if (!beanDefinition.equals(existingDefinition)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Overriding bean definition for bean '" + beanName +
                            "' with a different definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            } else {
                if (logger.isTraceEnabled()) {
                    logger.trace("Overriding bean definition for bean '" + beanName +
                            "' with an equivalent definition: replacing [" + existingDefinition +
                            "] with [" + beanDefinition + "]");
                }
            }
            //覆蓋beanDefinition
            this.beanDefinitionMap.put(beanName, beanDefinition);
        } else { //容器中不存在該beanDefinition的處理
            if (hasBeanCreationStarted()) {
                synchronized (this.beanDefinitionMap) { //對beanDefinition加鎖
                    //注入該beanDefinition
                    this.beanDefinitionMap.put(beanName, beanDefinition);
                    List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
                    updatedDefinitions.addAll(this.beanDefinitionNames);
                    updatedDefinitions.add(beanName);
                    this.beanDefinitionNames = updatedDefinitions;
                    if (this.manualSingletonNames.contains(beanName)) {
                        Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
                        updatedSingletons.remove(beanName);
                        this.manualSingletonNames = updatedSingletons;
                    }
                }
            }
            else {
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                this.beanDefinitionNames.add(beanName);
                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

    if (existingDefinition != null || containsSingleton(beanName)) {
        resetBeanDefinition(beanName);
    }
}

} ```

DefaultListableBeanFactory是預設使用的注入BeanDefinition的實現類,可以看到該實現類中對注入BeanDefinition做了很多的邏輯判斷,日常開發啟動容器過程中都會使用該實現類注入BeanDefinition進行後續的Bean注入。

Bean的注入

BeanDefinition注入後後續執行Bean的注入,bean注入的方式也是將bean注入到bean的容器中,因此在Spring中BeanDefinition和Bean都是通過容器化的方式操作的,那麼在Bean的注入中也通過對應的介面定義對Bean的操作,該介面就是SingletonBeanRegistry

SingletonBeanRegistry介面

該介面實現了對Bean的操作:

  • SingletonBeanRegistry#registerSingleton(將bean注入到容器中)
  • SingletonBeanRegistry#getSingleton(從容器中獲取bean)

```java public interface SingletonBeanRegistry {

//注入bean
void registerSingleton(String beanName, Object singletonObject);

//獲取bean
@Nullable
Object getSingleton(String beanName);
//是否存在bean
boolean containsSingleton(String beanName);

String[] getSingletonNames();

int getSingletonCount();

Object getSingletonMutex();

} ```

SingletonBeanRegistry的實現類

SingletonBeanRegistry的實現類有多個,分別為:

  • AbstractBeanFactory
  • DefaultListableBeanFactory
  • DefaultSingletonBeanRegistry
  • FactoryBeanRegistrySupport
  • AbstractAutowireCapableBeanFactory

下面說兩個有代表性的:AbstractBeanFactory和DefaultSingletonBeanRegistry

AbstractBeanFactory

該實現類是一個抽象類,即該類是bean的工廠類,其中主要實現的是可以複用的具體邏輯,該抽象類中包含獲取bean、beanPostProcessor、初始化bean、銷燬bean等對bean的操作抽象類。

```java public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {

//獲取bean的方式平時使用ApplicationContext就是最終呼叫該方法
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
    return doGetBean(name, requiredType, null, false);
}

@Override
public Object getBean(String name, Object... args) throws BeansException {
    return doGetBean(name, null, args, false);
}

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
        throws BeansException {

    return doGetBean(name, requiredType, args, false);
}

/**
* 從容器中獲取bean的主要邏輯
*/
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        //省略部分程式碼
        try {
            //先獲取beanDefinition
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 單例模式下獲取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);
            }

            else if (mbd.isPrototype()) {//原型模式下的bean的獲取
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    //原型模式每次都需要建立bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else { 
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("No Scope registered for scope 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;
        }
    }
    //省略部分程式碼
    return (T) bean;
}

//將實現beanPostProcessor的實現類加入到連結串列中用於對bean的前置或者後置處理
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
    Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
    // Remove from old position, if any
    this.beanPostProcessors.remove(beanPostProcessor);
    // Track whether it is instantiation/destruction aware
    if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
        this.hasInstantiationAwareBeanPostProcessors = true;
    }
    if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
        this.hasDestructionAwareBeanPostProcessors = true;
    }
    // Add to end of list
    this.beanPostProcessors.add(beanPostProcessor);
}

//銷燬bean的方法
@Override
public void destroyBean(String beanName, Object beanInstance) {
    destroyBean(beanName, beanInstance, getMergedLocalBeanDefinition(beanName));
}

protected void destroyBean(String beanName, Object bean, RootBeanDefinition mbd) {
    new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), getAccessControlContext()).destroy();
}

} ```

DefaultSingletonBeanRegistry

該實現類通過名字也可以推斷出該實現類是對單例bean的注入,該類中實現了bean的所有容器,平時開發過程中Spring容器啟動就是使用了該實現類中的容器,該實現類是對bean最終注入的實現,涉及的四個容器主要有:

  • singletonObjects
  • singletonFactories
  • earlySingletonObjects
  • registeredSingletons

四個容器其中三個的核心作用是解決迴圈依賴,這裡不展開說。

找一條主線梳理下Bean注入的過程,當BeanDefinition注入成功後,後續執行bean的注入,以AbstractAutowireCapableBeanFactory的實現為例,該實現類中會對bean的注入,整個注入的鏈路如下:

  1. 獲取資源資料:CommonAnnotationBeanPostProcessor#autowireResource
  2. 通過beanName解析bean:AbstractAutowireCapableBeanFactory#resolveBeanByName
  3. 呼叫抽象類中獲取bean:AbstractBeanFactory#getBean
  4. 執行抽象類中獲取bean的核心邏輯:AbstractBeanFactory#doGetBean
  5. bean不存在時建立bean:AbstractAutowireCapableBeanFactory#createBean
  6. 獲取單例bean:efaultSingletonBeanRegistry#getSingleton
  7. 單例bean不存在將類注入到容器中:DefaultSingletonBeanRegistry#addSingleton

```java public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { //單例bean的容器,開發過程中獲取的bean都是從該容器中獲取的:即所謂的一級快取 private final Map singletonObjects = new ConcurrentHashMap<>(256);

//單例bean的beanFactory的容器:即所謂的三級快取
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

//提前初始化的bean的容器,該容器的bean並沒有任何屬性值只是提前將bean注入到該容器中用於後續的判斷
//即所謂的二級快取
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

//已註冊的單例bean的beanName列表
private final Set<String> registeredSingletons = new LinkedHashSet<>(256);



//注入bean的方法
public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
    Assert.notNull(beanName, "Bean name must not be null");
    Assert.notNull(singletonObject, "Singleton object must not be null");
    synchronized (this.singletonObjects) {
        Object oldObject = this.singletonObjects.get(beanName);
        if (oldObject != null) {
            throw new IllegalStateException("Could not register object [" + singletonObject +
                                            "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
        }
        addSingleton(beanName, singletonObject);
    }
}

/**
* 將bean注入容器中,操作四個容器主要用於bean的迴圈依賴問題
*/
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);
    }
}

} ```

總結

以上就是對bean注入從原始碼的梳理,該梳理主要從bean注入前的準備(beanDefinition的注入)和bean注入的實現來完成,從整個梳理中學到最多的主要有兩點: - 抽象的思想:在BeanDefinition的實現和Bean的實現邏輯中,都完成高度抽象並且遵循單一原則和高度抽象,程式碼的可擴充套件性和複用性很高,我們作為開發者也可以通過Spring暴露的各種Registry介面實現對Bean的操作。 - 容器化思想:從BeanDefinition和Bean的注入來看,整個的實現思路都是基於容器化思想來實現的,將開發中需要關心的物件都例項化到容器中,開發者在使用時只要從容器中獲取即可,並且獲取bean的方式也很靈活,開發者在使用和擴充套件性上更便利。

對於原始碼的學習自己理解來說並不是背其中的程式碼,而是學習大佬實現程式碼的思想,為什麼可以抽象出擴充套件性這麼高的程式碼,並且從源頭梳理下來都能很輕鬆的按照主線一步一步梳理到目的地,這也是每個開發者需要學習的地方,提高自己程式碼的可讀性和可擴充套件性,能夠掌握面向物件的核心:封裝、繼承、多型