Spring 水滴石穿(五) 工廠實現之單例註冊 DefaultSingletonBeanRegistry

概述

這個class是個比較關鍵的類,它也是後面的完成工廠所繼承的頂級class,主要就是實現別名註冊接口和單例註冊接口,從而提供這些服務。緩存

屬性

//抑制異常最多100個
    private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;

    //一級緩存,緩存beanName和bean實例
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    //二級緩存,緩存beanName和單例工廠
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    //三級緩存,緩存beanName和提早暴露的bean實例
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    //已註冊的單例集合
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    //當前正在建立的單例名字集合
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    //建立檢測時須要排除的bean的名字集合
    private final Set<String> inCreationCheckExclusions =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    //已抑制的異常的集合
    @Nullable
    private Set<Exception> suppressedExceptions;

    //標識是否當前處於銷燬單例過程
    private boolean singletonsCurrentlyInDestruction = false;

    //可銷燬的bean實例
    private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

    //bean和它包含的bean之間的map
    private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

    //bean和依賴它的bean之間的map
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

    //bean和它依賴的bean之間的map,注意與上面的區別
    private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

方法

registerSingleton

public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
        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);
        }
    }

下面是真正作事情的方法,它會在一級緩存裏面添加數據,其餘緩存通通刪除this

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

這裏爲什麼要用倆個synchronized關鍵字?最外層的保留不就好了?設計

getSingleton

返回一個單例,注意這裏有個參數是否容許提早暴露一個實例化完成,但初始化未完成的bean,之因此要這樣設計是爲了解決循環引用問題,這個問題很簡單,就是beanA依賴beanB,beanB依賴beanA若是每一個都去等待另外一個bean建立完成就會陷入死循環中。code

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;
    }
相關文章
相關標籤/搜索