zoukankan      html  css  js  c++  java
  • Spring Bean 循环依赖

    创建 A 实例时需要 B,创建 B实例时需要 A。

    测试环境:https://gitee.com/jhxxb/MySpringBoot/tree/master/Spring-Base/src/test/java/BeanCircularDependency

    Spring IOC 中 Bean 的作用域有多种:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes

    默认 Bean 作用域为单例模式,Spring 解决循环依赖只能解决单例模式下的,无法解决多实例循环依赖,因为每次都需要 new,无法使用缓存

    单例模式下也无法解决构造器方式注入的循环依赖,必须要有一个 Bean 不是构造器注入

    总的来说 Spring 只能解决单例模式下的非构造器注入的循环依赖问题

    前置知识

    先清楚 Spring 中的两个概念

    • 实例化:就是 new 一个对象
    • 初始化:给 new 的对象设置属性

    还需要了解下 Spring IOC 中的三级缓存,平常所说的 IOC 容器就是一个 ConcurrentHashMap

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        /**
         * 一级缓存,单例对象的缓存:bean名称-bean实例,存放生成好的单例 Bean
         */
        private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
        /**
         * 三级缓存,单例工厂的缓存:bean名称-ObjectFactory,存放生成 bean 的工厂
         */
        private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
        /**
         * 二级缓存,早期的单例对象的缓存:bean名称-bean实例,存放实例化但未初始化(Bean 的属性还未填充)的单例 bean
         */
        private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

    过程,分三步

    1. A 创建过程中需要 B,于是 A 将自己放到三级缓里面,去实例化 B
    2. B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了 A,然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
    3. B 顺利初始化完毕,将自己放到一级缓存里面(此时 B 里面的 A 依然是创建中状态),然后回来接着创建 A,此时 B 已经创建结束,A 直接从一级缓存里面拿到 B,然后 A 完成创建,并将 A 自己放到一级缓存里面。

    源码(已删除部分影响阅读的代码,主要看处理流程)

    从获取对象开始,开始创建 A 对象,其实就是 IOC 的初始化流程:https://www.cnblogs.com/jhxxb/p/13609289.html

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
        @Override
        public void preInstantiateSingletons() throws BeansException {
            List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    if (isFactoryBean(beanName)) { // 是否为工厂 Bean
                    } else {
                        getBean(beanName); // 获取 Bean 对象
                    }
                }
            }

    进入到 getBean(beanName) 获取 Bean

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
        @SuppressWarnings("unchecked")
        protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) {
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            } else { // 没有获取到 A 对象,会进入到这里
                if (isPrototypeCurrentlyInCreation(beanName)) { // 检查正在创建中的 Bean 是否包含 A,如果是那就抛异常(循环依赖)
                    throw new BeanCurrentlyInCreationException(beanName);
                }
                try {// 是否有 Bean 需要在 A 之前创建
                    String[] dependsOn = mbd.getDependsOn();
                    if (dependsOn != null) {
                    }
    
                    if (mbd.isSingleton()) { // 创建单例模式 Bean
                        sharedInstance = getSingleton(beanName, () -> {
                            try {
                                return createBean(beanName, mbd, args);
                            } catch (BeansException ex) {
                                destroySingleton(beanName);
                                throw ex;
                            }
                        });
                        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                    } else if (mbd.isPrototype()) { // 创建原型模式 Bean
                    } else { // 其它 scope 类型的处理
                    }
                }
            }
    
            return adaptBeanInstance(name, beanInstance, requiredType);
        }
    
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        @Override
        @Nullable
        public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
            return getSingleton(beanName, true);
        }
    
        @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName); // 获取单例 Bean
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
            }
            return singletonObject; // A 没有创建过,直接到这里
        }
    
        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            synchronized (this.singletonObjects) {
                Object singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
                    boolean newSingleton = false;
                    try {
                        singletonObject = singletonFactory.getObject(); // 创建 Bean
                        newSingleton = true;
                    } catch (IllegalStateException ex) {
                        singletonObject = this.singletonObjects.get(beanName);
                        if (singletonObject == null) {
                            throw ex;
                        }
                    } finally {
                        afterSingletonCreation(beanName);
                    }
                    if (newSingleton) {
                        addSingleton(beanName, singletonObject);
                    }
                }
                return singletonObject;
            }
        }

    进入到 createBean(beanName, mbd, args) 开始创建 Bean

    public abstract class AbstractAutowireCapableBeanFactory extends org.springframework.beans.factory.support.AbstractBeanFactory implements AutowireCapableBeanFactory {
        @Override
        protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            try {
                // 给 Bean 一个返回代理对象的机会
                Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
                if (bean != null) {
                    return bean;
                }
            }
    
            try {
                Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 创建 Bean
                return beanInstance;
            }
        }
    
        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            if (instanceWrapper == null) {
                instanceWrapper = createBeanInstance(beanName, mbd, args); // 创建 Bean 实例
            }
    
            boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
            if (earlySingletonExposure) { // 放入三级缓存
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
    
            try {
                populateBean(beanName, mbd, instanceWrapper); // 属性填充,其中会实例化 B
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
    
            return exposedObject;
        }
    
        @SuppressWarnings("deprecation")
        protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
            if (hasInstAwareBpps) {
                for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                    PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        // 关于 postProcessPropertyValues 的实现,有几个处理器是非常关键的:
                        // 如 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor 等
                        pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {
                            return;
                        }
                    }
                    pvs = pvsToUse;
                }
            }
        }
    }
    
    public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
        @Deprecated
        @Override
        public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
            return postProcessProperties(pvs, bean, beanName);
        }
    
        @Override
        public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
            InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
            try {
                metadata.inject(bean, beanName, pvs);
            }
            return pvs;
        }
    
        private class AutowiredFieldElement extends InjectedElement {
            @Override
            protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
                Field field = (Field) this.member;
                Object value;
                if (this.cached) {
                    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
                } else {
                    try {
                        value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); // 获取 B 对象
                    }
                }
                if (value != null) {
                    ReflectionUtils.makeAccessible(field);
                    field.set(bean, value); // 设置实例对象 A 的属性 B
                }
            }
        }
    }
    
    public class InjectionMetadata {
        public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Collection<InjectedElement> checkedElements = this.checkedElements;
            Collection<InjectedElement> elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
            if (!elementsToIterate.isEmpty()) {
                for (InjectedElement element : elementsToIterate) {
                    element.inject(target, beanName, pvs); // AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement#inject
                }
            }
        }
    }
    
    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
        @Override
        @Nullable
        public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
            if (Optional.class == descriptor.getDependencyType()) {
            } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {
            } else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            } else {
                Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
                if (result == null) {
                    result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); // 解析依赖 B
                }
                return result;
            }
        }
    
        @Nullable
        public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
            try {
                Object shortcut = descriptor.resolveShortcut(this);
                if (shortcut != null) {
                    return shortcut;
                }
    
                if (instanceCandidate instanceof Class) {
                    instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); // 获取依赖的实例对象
                }
                Object result = instanceCandidate;
                return result;
            }
        }
    }
    
    public class DependencyDescriptor extends InjectionPoint implements Serializable {
        public Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) throws BeansException {
            return beanFactory.getBean(beanName); // 又回到了 getBean 方法获取实例 B
        }
    }

    创建 B 实例时同样会走到 DependencyDescriptor#resolveCandidate 来又创建 A,看 Spring 是怎么处理的

    public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
        @Override
        public Object getBean(String name) throws BeansException {
            return doGetBean(name, null, null, false);
        }
    
        @SuppressWarnings("unchecked")
        protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
            String beanName = transformedBeanName(name);
            Object beanInstance;
    
            Object sharedInstance = getSingleton(beanName);
            if (sharedInstance != null && args == null) { // 可以获取到 A 对象
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
            } else {
            }
    
            return adaptBeanInstance(name, beanInstance, requiredType);
        }
    
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        @Override
        @Nullable
        public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
            return getSingleton(beanName, true);
        }
    
        @Nullable
        protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存中获取单例 Bean
            if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
                // 会进入到这里,A 确实是正在创建中
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    synchronized (this.singletonObjects) {
                        singletonObject = this.singletonObjects.get(beanName); // 再次从一级缓存中获取
                        if (singletonObject == null) {
                            singletonObject = this.earlySingletonObjects.get(beanName); // 从二级缓存中获取
                            if (singletonObject == null) {
                                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); // 从三级缓存中获取,显然可以获取到
                                if (singletonFactory != null) {
                                    singletonObject = singletonFactory.getObject(); // 获取未赋属性值的 A 对象
                                    this.earlySingletonObjects.put(beanName, singletonObject); // 将 A 加入到二级缓存
                                    this.singletonFactories.remove(beanName); // 把 A 从三级缓存中移除
                                }
                            }
                        }
                    }
                }
            }
            return singletonObject; // 返回未赋属性值的 A 对象
        }

    继续看 B 对象的创建,它会在 A 对象之前创建出来

    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
            synchronized (this.singletonObjects) {
                Object singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
                    boolean newSingleton = false;
                    try {
                        singletonObject = singletonFactory.getObject(); // 创建 B 对象完成
                        newSingleton = true;
                    } finally {
                        afterSingletonCreation(beanName); // 从 singletonsCurrentlyInCreation 中移除
                    }
                    // 若是新创建的 Bean,那就执行 addSingleton 方法
                    if (newSingleton) {
                        addSingleton(beanName, singletonObject);
                    }
                }
                return singletonObject;
            }
        }
    
        protected void addSingleton(String beanName, Object singletonObject) { // Bean 彻底创建完成,添加进 singletonObjects
            synchronized (this.singletonObjects) {
                this.singletonObjects.put(beanName, singletonObject); // 把实例 B 放入一级缓存,B 直接从三级缓存到了一级缓存
                this.singletonFactories.remove(beanName); // 从三级缓存中删除
                this.earlySingletonObjects.remove(beanName); // 从二级缓存中删除
                this.registeredSingletons.add(beanName); // 记录已经创建好的 Bean 的名称,有顺序
            }
        }

    之后 A 会像 B 一样被创建出来。

    回到最开始,A 创建完后会继续创建 B,但这时就不会再走创建流程了,直接可以获取到 B

    public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
        @Override
        public void preInstantiateSingletons() throws BeansException {
            List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
            for (String beanName : beanNames) {
                RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
                if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                    if (isFactoryBean(beanName)) { // 是否为工厂 Bean
                    } else {
                        getBean(beanName); // 可以直接获取到 B 对象,没有了后续的创建流程
                    }
                }
            }

    Spring 中加入三级缓存的代码

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
        protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
            boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
            if (earlySingletonExposure) {
                addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            }
        }
    
        protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { // 从创建工厂中获取实例对象,会对 Bean 进行一些处理
            Object exposedObject = bean;
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
                for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
                    exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
                }
            }
            return exposedObject;
        }
    
    public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
        protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
            synchronized (this.singletonObjects) {
                if (!this.singletonObjects.containsKey(beanName)) {
                    this.singletonFactories.put(beanName, singletonFactory); // 加入三级缓存,是创建工厂,并非实例对象
                    this.earlySingletonObjects.remove(beanName);
                    this.registeredSingletons.add(beanName);
                }
            }
        }

    图示

    关闭 Spring 的循环依赖

    查看源码可以发现有一个 allowCircularReferences 属性可以控制

    public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
        /** Whether to automatically try to resolve circular references between beans. */
        private boolean allowCircularReferences = true;

    https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-dependency-resolution

  • 相关阅读:
    汉字乱码、加密后结果字符串不一致
    msgpack和TParams互相转换
    unigui监听会话开始和结束
    System.JSON.Builders.pas
    保证最终一致性的模式
    使用 Delta Sharing 协议进行数据共享
    dremio 16 升级问题
    graylog 4.0 运行
    supabase 开源firebase 可选工具
    cube.js 最新playground 说明
  • 原文地址:https://www.cnblogs.com/jhxxb/p/14421578.html
Copyright © 2011-2022 走看看