Spring 水滴石穿(五) 工厂实现之单例注册 DefaultSingletonBeanRegistry

概述

这个class是个比较关键的类,它也是后面的完成工厂所继承的顶级class,主要就是实现别名注册接口和单例注册接口,从而提供这些服务。

属性

    //抑制异常最多100个
    private static final int SUPPRESSED_EXCEPTIONS_LIMIT = 100;

    //一级缓存,缓存beanName和bean实例
    private final Map singletonObjects = new ConcurrentHashMap<>(256);

    //二级缓存,缓存beanName和单例工厂
    private final Map> singletonFactories = new HashMap<>(16);

    //三级缓存,缓存beanName和提前暴露的bean实例
    private final Map earlySingletonObjects = new HashMap<>(16);

    //已注册的单例集合
    private final Set registeredSingletons = new LinkedHashSet<>(256);

    //当前正在创建的单例名字集合
    private final Set singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    //创建检测时需要排除的bean的名字集合
    private final Set inCreationCheckExclusions =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    //已抑制的异常的集合
    @Nullable
    private Set suppressedExceptions;

    //标识是否当前处于销毁单例过程
    private boolean singletonsCurrentlyInDestruction = false;

    //可销毁的bean实例
    private final Map disposableBeans = new LinkedHashMap<>();

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

    //bean和依赖它的bean之间的map
    private final Map> dependentBeanMap = new ConcurrentHashMap<>(64);

    //bean和它依赖的bean之间的map,注意与上面的区别
    private final Map> 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);
        }
    }

下面是真正做事情的方法,它会在一级缓存里面添加数据,其他缓存统统删除

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创建完成就会陷入死循环中。
这个方法实现了接口中的定义,值得注意的是还有个同名重载方法,并不是直接实现接口。

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

同名重载方法

这个方法并没有提前暴露引用,主要就是在找不到对应单例的情况下创建单例,并放到缓存中
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException}
                //创建前检查
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                try {
                    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.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    throw ex;
                }
                finally {
                    //创建后检查
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

值得注意的是有个创建前检测和创建后检测

protected void beforeSingletonCreation(String beanName) {
        //创建检测排除表中没有包含当前beanName,添加到单例创建列表失败就意味着继续创建意味着数据不一致,所以抛出异常
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

protected void afterSingletonCreation(String beanName) {
        //创建检测排除表中没有包含当前beanName,从单例创建列表移除失败就意味着数据将不一致,所以抛出异常
        if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }

removeSingleton

没什么好说的,相关缓存中全部移除

protected void removeSingleton(String beanName) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.remove(beanName);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.remove(beanName);
        }
    }

isDependent

这里的alreadySeen用来记录已经查找过的beanName,因为要判断bean之间的依赖关系,不仅仅是查看这个bean的直接依赖还要去这个bean的依赖的依赖去查找,所以需要递归,而递归的时候如果某个beanName已经被验证过,就会跳过,所以才需要这个alreadySeen来记录校验过得beanName

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);
        if (dependentBeans == null) {
            return false;
        }
        if (dependentBeans.contains(dependentBeanName)) {
            return true;
        }
        for (String transitiveDependency : dependentBeans) {
            if (alreadySeen == null) {
                alreadySeen = new HashSet<>();
            }
            alreadySeen.add(beanName);
            if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
                return true;
            }
        }
        return false;
    }

destroyBean

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

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

        // Trigger destruction of contained beans...
        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.
        synchronized (this.dependentBeanMap) {
            for (Iterator>> it = this.dependentBeanMap.entrySet().iterator(); it.hasNext();) {
                Map.Entry> entry = it.next();
                Set dependenciesToClean = entry.getValue();
                dependenciesToClean.remove(beanName);
                if (dependenciesToClean.isEmpty()) {
                    it.remove();
                }
            }
        }

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

销毁单例的流程

1.从依赖表中删除当前bean,依赖表是对象与其依赖对象的关系表
2.遍历bean依赖的对象,挨个调用销毁单例方法
3.如果是可销毁对象,就调用其对象销毁方法
4.遍历bean的内部bean对象,挨个调用销毁单例方法
5.迭代整个依赖表,为什么?因为要从依赖表中找到曾经依赖过当前bean的对象,从它们的依赖对象集合中删除这个bean,从而完成当前bean的缓存清理工作
6.从被依赖表中移除当前bean,不需要遍历!因为这个map本就是维护bean和依赖其的对象的关系表

你可能感兴趣的:(java,spring)