Spring学習のソース分析--D e f a ultSingletonBeanRegistry


DefaultSingletonBeanRegistry
DefaultSingletonBeanRegistryクラスはSimpleAliasRegistryを継承し、SingletonBeanRegistryを実現するインタフェースを継承します.Beanの登録、破棄、および依存関係の登録と破棄を処理します.
クラス構造
切り取り部分
フィールド
//        : beanname bean  
private final Map singletonObjects = new ConcurrentHashMap<>(256);
//        : beanname ObjectFactory
private final Map> singletonFactories = new HashMap<>(16);
//          : beanname bean  
private final Map earlySingletonObjects = new HashMap<>(16);
//         ,          beanname
private final Set registeredSingletons = new LinkedHashSet<>(256);
//         beanName   
private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//       bean   
private final Set inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//     
private Set suppressedExceptions;
//        bean 
private boolean singletonsCurrentlyInDestruction = false;
//    bean  
private final Map disposableBeans = new LinkedHashMap<>();
//   bean   bean    
private final Map> containedBeanMap = new ConcurrentHashMap<>(16);
//   bean     bean   ,  bcd  a,    key a,bcd value
private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);
//   bean   bean     ,  a  bcd,    key a,bcd value
private final Map> dependenciesForBeanMap = new ConcurrentHashMap<>(64);

メソッド解析
registerSingleton
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);
    }
}

addSingleton
キャッシュに単一のインスタンスを追加
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        //          
        this.singletonObjects.put(beanName, singletonObject);
        //             , singletonFactories earlySingletonObjects     
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        //       bean
        this.registeredSingletons.add(beanName);
    }
}

addSingletonFactory
//         ,        getObject  
protected void addSingletonFactory(String beanName, ObjectFactory> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

getSingleton
public Object getSingleton(String beanName) {
    return getSingleton(beanName, true);
}
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) {//allowEarlyReference     singletonFactories  
                ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {//       ,  getObject    
                    singletonObject = singletonFactory.getObject();
                    // singletonFactories       earlySingletonObjects 
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //           ,        ,     earlySingletonObjects  
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

public Object getSingleton(String beanName, ObjectFactory> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        Object singletonObject = this.singletonObjects.get(beanName);
        if (singletonObject == null) {
            //      bean,    
            if (this.singletonsCurrentlyInDestruction) {
                throw new BeanCreationNotAllowedException(beanName,
                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
            }
            //      
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            //         ,       
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                //   ObjectFactory getObject  bean
                singletonObject = singletonFactory.getObject();
                newSingleton = true;
            }
            catch (IllegalStateException ex) {
                // Has the singleton object implicitly appeared in the meantime ->
                // if yes, proceed with it since the exception indicates that state.
                //            bean
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    throw ex;
                }
            }
            catch (BeanCreationException ex) {
                if (recordSuppressedExceptions) {
                    for (Exception suppressedException : this.suppressedExceptions) {
                        ex.addRelatedCause(suppressedException);
                    }
                }
                throw ex;
            }
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                //      
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                //      bean,       ,          bean,          ,      
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

onSuppressedException
登録中に発生した例外を例外セットに追加
protected void onSuppressedException(Exception ex) {
    synchronized (this.singletonObjects) {
        if (this.suppressedExceptions != null) {
            this.suppressedExceptions.add(ex);
        }
    }
}

removeSingleton
単一のインスタンスを削除します.この4つは同時に削除されます.
protected void removeSingleton(String beanName) {
    synchronized (this.singletonObjects) {
        this.singletonObjects.remove(beanName);
        this.singletonFactories.remove(beanName);
        this.earlySingletonObjects.remove(beanName);
        this.registeredSingletons.remove(beanName);
    }
}

containsSingleton
getSingletonNames
getSingletonCount
singletonObjects、registeredSingletonsの情報読み出し
@Override
public boolean containsSingleton(String beanName) {
    //        
    return this.singletonObjects.containsKey(beanName);
}

@Override
public String[] getSingletonNames() {
    //        bean
    synchronized (this.singletonObjects) {
        return StringUtils.toStringArray(this.registeredSingletons);
    }
}

@Override
public int getSingletonCount() {
    //        
    synchronized (this.singletonObjects) {
        return this.registeredSingletons.size();
    }
}

setCurrentlyInCreation
チェックしないbeanNameの設定
public void setCurrentlyInCreation(String beanName, boolean inCreation) {
    Assert.notNull(beanName, "Bean name must not be null");
    if (!inCreation) {
        this.inCreationCheckExclusions.add(beanName);
    }
    else {
        this.inCreationCheckExclusions.remove(beanName);
    }
}

isCurrentlyInCreation
isActuallyInCreation
isSingletonCurrentlyInCreation
現在作成されているbean
public boolean isCurrentlyInCreation(String beanName) {
    Assert.notNull(beanName, "Bean name must not be null");
    //     beanName       ,  false,        
    //     beanName   ,             bean
    return (!this.inCreationCheckExclusions.contains(beanName) && isActuallyInCreation(beanName));
}
protected boolean isActuallyInCreation(String beanName) {
    return isSingletonCurrentlyInCreation(beanName);
}
public boolean isSingletonCurrentlyInCreation(String beanName) {
    return this.singletonsCurrentlyInCreation.contains(beanName);
}

beforeSingletonCreation
afterSingletonCreation
protected void beforeSingletonCreation(String beanName) {
    //     beanName   ,  add       ,    false,        ,   
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

protected void afterSingletonCreation(String beanName) {
    //     beanName   ,  remove    ,    false,        。
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}

registerDisposableBean
使い捨てbeanインスタンスの登録
public void registerDisposableBean(String beanName, DisposableBean bean) {
    synchronized (this.disposableBeans) {
        this.disposableBeans.put(beanName, bean);
    }
}

registerContainedBean
public void registerContainedBean(String containedBeanName, String containingBeanName) {
    synchronized (this.containedBeanMap) {
        //     key containingBeanName value,    bean    ,      
        Set containedBeans =
                this.containedBeanMap.computeIfAbsent(containingBeanName, k -> new LinkedHashSet<>(8));
        //            ,     ,   ,       
        if (!containedBeans.add(containedBeanName)) {
            return;
        }
    }
    registerDependentBean(containedBeanName, containingBeanName);
}

registerDependentBean
canonicalNameメソッドはSimpleAliasRegistryに属するメソッドです.
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);

    synchronized (this.dependentBeanMap) {
        Set dependentBeans =
                this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
        //            ,     ,   ,       
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }

    synchronized (this.dependenciesForBeanMap) {
        Set dependenciesForBean =
                this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
        //       
        dependenciesForBean.add(canonicalName);
    }
}

isDependent
dependentBeanNameがbeanNameに依存しているかどうか
protected boolean isDependent(String beanName, String dependentBeanName) {
    synchronized (this.dependentBeanMap) {
        return isDependent(beanName, dependentBeanName, null);
    }
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set alreadySeen) {
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    String canonicalName = canonicalName(beanName);
    Set dependentBeans = this.dependentBeanMap.get(canonicalName);
    //   ,    bean  beanName,    false
    if (dependentBeans == null) {
        return false;
    }
    //    bean  beanName,    dependentBeanName,  true
    if (dependentBeans.contains(dependentBeanName)) {
        return true;
    }
    //    bean  beanName,     dependentBeanName
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        alreadySeen.add(beanName);
        //        
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}

hasDependentBean
他のオブジェクト依存指定beanがあるかどうか
protected boolean hasDependentBean(String beanName) {
    return this.dependentBeanMap.containsKey(beanName);
}

getDependentBeans
指定したbeanに依存する配列を返す
public String[] getDependentBeans(String beanName) {
    Set dependentBeans = this.dependentBeanMap.get(beanName);
    if (dependentBeans == null) {
        return new String[0];
    }
    synchronized (this.dependentBeanMap) {
        return StringUtils.toStringArray(dependentBeans);
    }
}

getDependenciesForBean
指定したbeanを返し、他のbeanに依存する配列を返します.
public String[] getDependenciesForBean(String beanName) {
    Set dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
    if (dependenciesForBean == null) {
        return new String[0];
    }
    synchronized (this.dependenciesForBeanMap) {
        return StringUtils.toStringArray(dependenciesForBean);
    }
}

destroySingletons
廃棄ケース
public void destroySingletons() {
    if (logger.isTraceEnabled()) {
        logger.trace("Destroying singletons in " + this);
    }
    //         
    synchronized (this.singletonObjects) {
        this.singletonsCurrentlyInDestruction = true;
    }

    String[] disposableBeanNames;
    synchronized (this.disposableBeans) {
        disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
    }
    //   disposableBeans    bean
    for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
        destroySingleton(disposableBeanNames[i]);
    }
    //   containedBeanMap、dependentBeanMap、dependenciesForBeanMap
    this.containedBeanMap.clear();
    this.dependentBeanMap.clear();
    this.dependenciesForBeanMap.clear();
    //       
    clearSingletonCache();
}

clearSingletonCache
シングル・キャッシュのパージ
protected void clearSingletonCache() {
    synchronized (this.singletonObjects) {
        this.singletonObjects.clear();
        this.singletonFactories.clear();
        this.earlySingletonObjects.clear();
        this.registeredSingletons.clear();
        //     ,     false
        this.singletonsCurrentlyInDestruction = false;
    }
}

destroySingleton
単例beanの破棄
public void destroySingleton(String beanName) {
    // Remove a registered singleton of the given name, if any.
    //       
    removeSingleton(beanName);

    // Destroy the corresponding DisposableBean instance.
    DisposableBean disposableBean;
    synchronized (this.disposableBeans) {
        //  disposableBeans  ,   beanName     ,      
        disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
    }
    //   bean
    destroyBean(beanName, disposableBean);
}

destroyBean
消費bean
protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
    // Trigger destruction of dependent beans first...
    Set dependencies;
    //       beanName bean
    synchronized (this.dependentBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        //       beanName bean
        dependencies = this.dependentBeanMap.remove(beanName);
    }
    if (dependencies != null) {
        if (logger.isTraceEnabled()) {
            logger.trace("Retrieved dependent beans for bean '" + beanName + "': " + dependencies);
        }
        //       beanName bean
        for (String dependentBeanName : dependencies) {
            destroySingleton(dependentBeanName);
        }
    }

    // Actually destroy the bean now...
    if (bean != null) {
        try {
            //   bean
            bean.destroy();
        }
        catch (Throwable ex) {
            if (logger.isInfoEnabled()) {
                logger.info("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
            }
        }
    }

    // Trigger destruction of contained beans...
    //   beanName      bean
    Set containedBeans;
    synchronized (this.containedBeanMap) {
        // Within full synchronization in order to guarantee a disconnected Set
        containedBeans = this.containedBeanMap.remove(beanName);
    }
    if (containedBeans != null) {
        for (String containedBeanName : containedBeans) {
            destroySingleton(containedBeanName);
        }
    }

    // Remove destroyed bean from other beans' dependencies.
    //        bean  ,        
    synchronized (this.dependentBeanMap) {
        for (Iterator>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
            Map.Entry> entry = it.next();
            Set dependenciesToClean = entry.getValue();
            dependenciesToClean.remove(beanName);
            //       beanName,       ,    
            if (dependenciesToClean.isEmpty()) {
                it.remove();
            }
        }
    }

    // Remove destroyed bean's prepared dependency information.
    //     bean     bean   
    this.dependenciesForBeanMap.remove(beanName);
}

getSingletonMutex
ロック操作に使用してsingletonObjectsを返し、このオブジェクトをメソッドで露出します.
public final Object getSingletonMutex() {
    return this.singletonObjects;
}