菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
301
0

Spring依赖循环

原创
05/13 14:22
阅读数 63511

DefaultSingletonBeanRegistry源码

源码注释:

  public class DefaultSingletonBeanRegistry 
  extends SimpleAliasRegistry implements SingletonBeanRegistry {

    // 已经创建的单实例 bean 的 beanName 和 instance 的映射关系集
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

    // 正在创建的的单实例 bean 的 beanName 和 ObjectFactory instance 的映射关系集
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

    // 正在创建的单实例 bean 的 beanName 和 instance 的映射关系集, 用于解决循环依赖
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

    // 已经成功创建的单实例 bean 的 beanName 集合
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

    // 正在创建的单实例 bean 的 beanBean 集合
    private final Set<String> singletonsCurrentlyInCreation 
      = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    // 在检测某个 bean 是否正在创建时需要排除的在检测外的 bean 的 beanName 集合
    private final Set<String> inCreationCheckExclusions 
      = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

    // 这个记录方法调用链出现的异常
    @Nullable
    private Set<Exception> suppressedExceptions;

    //表示当前所有的单例是否正在被销毁
    private boolean singletonsCurrentlyInDestruction = false;

    // 已经销毁的单实例 bean 的 beanName 和 instance 的映射关系集
    private final Map<String, Object> disposableBeans = new LinkedHashMap<>();

    /**
     * 外部bean与被包含在外部bean的所有内部bean集合包含关系的缓存
     * Map between containing bean names: bean name to Set of bean names that the
     * bean contains.
     */
    private final Map<String, Set<String>> containedBeanMap = new ConcurrentHashMap<>(16);

    /**
     * dependentBeanMap存放的是  依赖当前bean的 所有的bean的集合
     * Map between dependent bean names: bean name to Set of dependent bean names.
     */
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);

    // bean 实例化时需要依赖的 bean 的 beanName 集合映射关系集
    private final Map<String, Set<String>> dependenciesForBeanMap
      = new ConcurrentHashMap<>(64);

    // SingletonBeanRegistry接口的registerSingleton方法的实现
    @Override
    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);
        }
    }

    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            // 加入到已创建集合
            this.singletonObjects.put(beanName, singletonObject);
            // 从正在创建的缓存集合中移除
            this.singletonFactories.remove(beanName);
            // 从正在创建的集合中移除
            this.earlySingletonObjects.remove(beanName);
            // beanName 添加到已注册的 beanName 集合中
            this.registeredSingletons.add(beanName);
        }
    }

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

    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }

    // allowEarlyReference: 当 singletonObjects 和 earlySingletonObjects 都没有取到时,
    // 是否到 singletonFactories 缓存中去取
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 先从 singletonObjects 中获取
        Object singletonObject = this.singletonObjects.get(beanName);
        // 如果不存在判断是否正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            synchronized (this.singletonObjects) {
                // 如果正在创建, 从 earlySingletonObjects 获取 
                singletonObject = this.earlySingletonObjects.get(beanName);
                //  如果 earlySingletonObjects 没有取到, 就去 singletonFactories 去取
                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;
    }

    // 返回一个单实例 bean, 如果这个 bean 不存在, 就会创建并注册
    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) {
                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 + "'");
                }

                // 主要判断 bean 是否正在创建, 如果正在创建, 抛出异常
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 从 ObjectFactory 的 getObject 获取实例
                    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) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    } 
                    // 创建单实例 bean 失败处理
                    afterSingletonCreation(beanName);
                }

                // 如果是一个新的单实例 bean, 添加单实例 bean
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

    // 记录发生的异常栈
    protected void onSuppressedException(Exception ex) {
        synchronized (this.singletonObjects) {
            if (this.suppressedExceptions != null) {
                this.suppressedExceptions.add(ex);
            }
        }
    }
  
    // 移除指定的单实例 bean
    protected void removeSingleton(String beanName) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.remove(beanName);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.remove(beanName);
        }
    }

    // 是否包含指定的 bean
    @Override
    public boolean containsSingleton(String beanName) {
        return this.singletonObjects.containsKey(beanName);
    }

    // 返回所有的单实例名称
    @Override
    public String[] getSingletonNames() {
        synchronized (this.singletonObjects) {
            return StringUtils.toStringArray(this.registeredSingletons);
        }
    }

    // 获取单实例的数量
    @Override
    public int getSingletonCount() {
        synchronized (this.singletonObjects) {
            return this.registeredSingletons.size();
        }
    }

    // 指定 bean 是否在检测是否正在创建时是否需要排除
    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);
        }
    }

    // 判断指定的 bean 是否正在创建
    public boolean isCurrentlyInCreation(String beanName) {
        Assert.notNull(beanName, "Bean name must not be null");
        return (!this.inCreationCheckExclusions.contains(beanName) &&
                isActuallyInCreation(beanName));
    }

    protected boolean isActuallyInCreation(String beanName) {
        return isSingletonCurrentlyInCreation(beanName);
    }

    // 判断单实例 bean 是否正在创建
    public boolean isSingletonCurrentlyInCreation(String beanName) {
        return this.singletonsCurrentlyInCreation.contains(beanName);
    }

    // 创建单实例 bean 的前置处理, 主要判断 bean 是否正在创建
    // 如果没有创建, 从正在创建的集合中移除, 如果正在创建, 抛出异常
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) && 
            !this.singletonsCurrentlyInCreation.add(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }
    }

    // 创建单实例 bean 的前置处理, 从正在创建的集合中移除
    protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName)
                && !this.singletonsCurrentlyInCreation.remove(beanName)) {
            throw new IllegalStateException("Singleton '" + beanName +
                                            "' isn't currently in creation");
        }
    }

    // 将 bean 添加到需要销毁的集合中
    public void registerDisposableBean(String beanName, DisposableBean bean) {
        synchronized (this.disposableBeans) {
            this.disposableBeans.put(beanName, bean);
        }
    }

    /**
     * Register a containment relationship between two beans, e.g. between an inner
     * bean and its containing outer bean.
     * <p>
     * Also registers the containing bean as dependent on the contained bean in
     * terms of destruction order.
     * 
     * @param containedBeanName  the name of the contained (inner) bean
     * @param containingBeanName the name of the containing (outer) bean
     * @see #registerDependentBean
     */
    // ??? 暂时没看懂这个 containedBeanMap 的作用
    public void registerContainedBean(String containedBeanName, 
                                      String containingBeanName) {
        synchronized (this.containedBeanMap) {
            Set<String> containedBeans 
              = this.containedBeanMap.computeIfAbsent(containingBeanName,
                    k -> new LinkedHashSet<>(8));
            if (!containedBeans.add(containedBeanName)) {
                return;
            }
        }
        registerDependentBean(containedBeanName, containingBeanName);
    }

    // 为指定的 bean 添加一个依赖的 bean
    public void registerDependentBean(String beanName, String dependentBeanName) {
        String canonicalName = canonicalName(beanName);

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

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

    // 判断一个 bean 是否依赖另一个 bean
    protected boolean isDependent(String beanName, String dependentBeanName) {
        synchronized (this.dependentBeanMap) {
            return isDependent(beanName, dependentBeanName, null);
        }
    }

    private boolean isDependent(String beanName, String dependentBeanName, 
                                @Nullable Set<String> alreadySeen) {
        if (alreadySeen != null && alreadySeen.contains(beanName)) {
            return false;
        }
        String canonicalName = canonicalName(beanName);
        Set<String> 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;
    }

    // 判断一个 bean 是否有依赖
    protected boolean hasDependentBean(String beanName) {
        return this.dependentBeanMap.containsKey(beanName);
    }

    // 获取一个 bean 的所有依赖的 bean 的 beanName 集合
    public String[] getDependentBeans(String beanName) {
        Set<String> dependentBeans = this.dependentBeanMap.get(beanName);
        if (dependentBeans == null) {
            return new String[0];
        }
        synchronized (this.dependentBeanMap) {
            return StringUtils.toStringArray(dependentBeans);
        }
    }

    // 返回创建这个 bean 时所依赖的的 bean 的 beanName 集合
    public String[] getDependenciesForBean(String beanName) {
        Set<String> dependenciesForBean = this.dependenciesForBeanMap.get(beanName);
        if (dependenciesForBean == null) {
            return new String[0];
        }
        synchronized (this.dependenciesForBeanMap) {
            return StringUtils.toStringArray(dependenciesForBean);
        }
    }

    // 销毁所有的单实例
    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());
        }

        // 销毁依赖的 bean
        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            destroySingleton(disposableBeanNames[i]);
        }

        this.containedBeanMap.clear();
        this.dependentBeanMap.clear();
        this.dependenciesForBeanMap.clear();
        clearSingletonCache();
    }

    // 清除所有缓存
    protected void clearSingletonCache() {
        synchronized (this.singletonObjects) {
            this.singletonObjects.clear();
            this.singletonFactories.clear();
            this.earlySingletonObjects.clear();
            this.registeredSingletons.clear();
            this.singletonsCurrentlyInDestruction = false;
        }
    }

    // 销毁指定的 bean
    public void destroySingleton(String beanName) {
        // Remove a registered singleton of the given name, if any.
        removeSingleton(beanName);
        DisposableBean disposableBean;
        synchronized (this.disposableBeans) {
            disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
        }
        destroyBean(beanName, disposableBean);
    }

    // 销毁依赖的 bean
    protected void destroyBean(String beanName, @Nullable DisposableBean bean) {
        // 先销毁依赖的 bean
        Set<String> dependencies;
        synchronized (this.dependentBeanMap) {
            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.isInfoEnabled()) {
                    logger.info("Destroy method on bean with name '" + 
                                beanName + "' threw an exception", ex);
                }
            }
        }

        // Trigger destruction of contained beans...
        Set<String> 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<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();
                }
            }
        }

        // 清除缓存
        this.dependenciesForBeanMap.remove(beanName);
    }

    // 返回已创建的实例的缓存
    public final Object getSingletonMutex() {
        return this.singletonObjects;
    }
}

具体原理说明

三级缓存

上述源码中,主要是下面的3个对象核心,实现3级缓存

/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

/**
bean 的获取过程:先从一级获取,失败再从二级、三级里面获取

创建中状态:是指对象已经 new 出来了但是所有的属性均为 null 等待被 init
*/

检测循环依赖的过程如下:

  • A 创建过程中需要 B,于是 A 将自己放到三级缓里面 ,去实例化 B

  • B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了!

    • 然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
    • B 顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)
  • 然后回来接着创建 A,此时 B 已经创建结束,直接从一级缓存里面拿到 B ,然后完成创建,并将自己放到一级缓存里面

  • 如此一来便解决了循环依赖的问题

根据beanName获取对应的对象

	/**
	 * Return the (raw) singleton object registered under the given name.
	 * <p>Checks already instantiated singletons and also allows for an early
	 * reference to a currently created singleton (resolving a circular reference).
	 * @param beanName the name of the bean to look for
	 * @param allowEarlyReference whether early references should be created or not
	 * @return the registered singleton object, or {@code null} if none found
	 */
	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 != NULL_OBJECT ? singletonObject : null);
	}

手工简化版依赖循环

/**
 * 放置创建好的bean Map
 */
private static Map < String, Object > cacheMap = new HashMap < > (2);

public static void main(String[] args) {
    // 假装扫描出来的对象
    Class[] classes = { A.class, B.class };
    // 假装项目初始化实例化所有bean
    for (Class aClass: classes) {
        getBean(aClass);
    }
    // check
    System.out.println(getBean(B.class).getA() == getBean(A.class));
    System.out.println(getBean(A.class).getB() == getBean(B.class));
}

@SneakyThrows
private static < T > T getBean(Class < T > beanClass) {
    // 本文用类名小写 简单代替bean的命名规则
    String beanName = beanClass.getSimpleName().toLowerCase();
    // 如果已经是一个bean,则直接返回
    if (cacheMap.containsKey(beanName)) {
        return (T) cacheMap.get(beanName);
    }
    // 将对象本身实例化
    Object object = beanClass.getDeclaredConstructor().newInstance();
    // 放入缓存
    cacheMap.put(beanName, object);
    // 把所有字段当成需要注入的bean,创建并注入到当前bean中
    Field[] fields = object.getClass().getDeclaredFields();
    for (Field field: fields) {
        field.setAccessible(true);
        // 获取需要注入字段的class
        Class < ? > fieldClass = field.getType();
        String fieldBeanName = fieldClass.getSimpleName().toLowerCase();
        // 如果需要注入的bean,已经在缓存Map中,那么把缓存Map中的值注入到该field即可
        // 如果缓存没有 继续创建
        field.set(object, cacheMap.containsKey(fieldBeanName) ?
            cacheMap.get(fieldBeanName) : getBean(fieldClass));
    }
    // 属性填充完成,返回
    return (T) object;
}

总结

Spring虽然解决了Bean对象的循环依赖,但是是有条件限制的

  • 对象必须为单例模式,Spring的容器只缓存作用域为singleton的对象
  • 必须为属性注入循环依赖,如果为构造函数则不行

参考

帮助你更好的理解Spring循环依赖

图解 Spring 循环依赖,写得太好了!

面试中被问Spring循环依赖的三种方式!!!

第三章 spring-bean之DefaultSingletonBeanRegistry(3)

Spring源码分析3-DefaultSingletonBeanRegistry

Spring-源码阅读DefaultSingletonBeanRegistry

高频面试题:Spring 如何解决循环依赖?

Spring 如何解决循环依赖的问题

发表评论

0/200
301 点赞
0 评论
收藏