zoukankan      html  css  js  c++  java
  • 建议收藏!利用Spring解决循环依赖,深入源码给你讲明白!

    前置知识

    • 只有单例模式下的bean会通过三级缓存提前暴露来解决循环依赖的问题。而非单例的bean每次获取都会重新创建,并不会放入三级缓存,所以多实例的bean循环依赖问题不能解决。

    • 首先需要明白处于各个阶段的bean被放在哪里。在DefaultSingletonBeanRegistry类中

        /** 一级缓存,存放经历完整生命周期的bean*/
    	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
     
    	/** 三级缓存,存放FactoryBean */
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
     
    	/** 二级缓存,存放刚刚创建出来还未进行属性赋值的bean */
    	private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
    
    

    测试代码

    public class ServiceAA {
     
        public ServiceAA() {
            System.out.println("AA已经创建");
        }
     
        private ServiceBB serviceBB;
     
        public ServiceBB getServiceBB() {
            return serviceBB;
        }
     
        public void setServiceBB(ServiceBB serviceBB) {
            this.serviceBB = serviceBB;
        }
    }
    
    
    public class ServiceBB {
        public ServiceBB() {
            System.out.println("BB已经创建");
        }
        private ServiceAA serviceAA;
     
        public ServiceAA getServiceAA() {
            return serviceAA;
        }
     
        public void setServiceAA(ServiceAA serviceAA) {
            this.serviceAA = serviceAA;
        }
    }
    
    
        <bean id="serviceAA" class="org.song.circularDepend.ServiceAA" >
            <property name="serviceBB" ref="serviceBB"/>
        </bean>
     
        <bean id="serviceBB" class="org.song.circularDepend.ServiceBB">
            <property name="serviceAA" ref="serviceAA"/>
        </bean>
    
    

    流程

    • 在上述代码中,ServiceAA 依赖于ServiceBB,同时ServiceBB也依赖于ServiceAA ,各个bean相互依赖,最终形成了闭环,那么spring是如何解决此问题的呢?

    • 可以简单理解为spring创建bean分为两个步骤,第一步是创建原始bean,第二步就是对属性进行赋值和初始化等操作。

    • 每次创建bean之前都会去缓存中查找是否有当前bean,因为是单例,只能有一个

    • 当创建bean serviceAA后,会将其加入三级缓存中,然后需要填充bean的属性了

    • 这时候发现需要依赖于bean serviceBB,接下来又去创建serviceBB。重复1-3的流程

    • 这时候发现需要依赖于bean serviceAA,发现三级缓存中存在bean serviceAA,所以不需要重复创建。把bean serviceAA注入bean serviceBB

    • 这个时候bean serviceBB创建好了,递归继续去为bean serviceAA进行属性赋值。闭环完成

    源码

    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			try {
    				
     
    				//初始化剩下的单实例bean
    				finishBeanFactoryInitialization(beanFactory);
     
    				
    			}
     
    			catch (BeansException ex) {
    				if (logger.isWarnEnabled()) {
    					logger.warn("Exception encountered during context initialization - " +
    							"cancelling refresh attempt: " + ex);
    				}
     
    				// Destroy already created singletons to avoid dangling resources.
    				destroyBeans();
     
    				// Reset 'active' flag.
    				cancelRefresh(ex);
     
    				// Propagate exception to caller.
    				throw ex;
    			}
     
    			finally {
    				// Reset common introspection caches in Spring's core, since we
    				// might not ever need metadata for singleton beans anymore...
    				resetCommonCaches();
    			}
    		}
    	}
    
    
    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    		//实例化单实例bean
    		beanFactory.preInstantiateSingletons();
    	}
    
    
    @Override
    	public void preInstantiateSingletons() throws BeansException {
    		
    		getBean(beanName);
    			
    	}
    
    
    public Object getBean(String name) throws BeansException {
    		return doGetBean(name, null, null, false);
    	}
    
    
    protected <T> T doGetBean(
    			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
    			throws BeansException {
     
    		final String beanName = transformedBeanName(name);
    		Object bean;
     
    		//首先查询缓存中是否存在bean,当前为null
    		Object sharedInstance = getSingleton(beanName);
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            if (mbd.isSingleton()) {
    					sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
    						@Override
    						public Object getObject() throws BeansException {
    							try {
                                    //创建bean
    								return createBean(beanName, mbd, args);
    							}
    							catch (BeansException ex) {
    								destroySingleton(beanName);
    								throw ex;
    							}
    						}
    					});
    					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    		}
    }
    
    
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            //一级缓存中是否存在当前bean(serviceAA),此时为null
            //isSingletonCurrentlyInCreation(beanName),当前bean是否被标记为
            //正在创建,返回false,所以后续不执行,直接返回null
    		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);
    	}
    
    
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    	beforeSingletonCreation(beanName);
    				
    	singletonObject = singletonFactory.getObject();
    				
    	addSingleton(beanName, singletonObject);
    				
    	return (singletonObject != NULL_OBJECT ? singletonObject : null);
    	}
    
    protected void beforeSingletonCreation(String beanName) {
            //将当前正在创建的bean serviceAA 标记为正在创建中,添加到集合singletonsCurrentlyInCreation中
    		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
    			throw new BeanCurrentlyInCreationException(beanName);
    		}
    	}
    
    
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    		//开始真正的创建bean service AA
    		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    		
    		return beanInstance;
    	}
    
    
    protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
    			throws BeanCreationException {
    		BeanWrapper instanceWrapper = null;
                //用反射创建初始bean serviceAA,源码部分略过
    			instanceWrapper = createBeanInstance(beanName, mbd, args);
    		//当前为true
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
                //如果一级缓存中没有当前bean,就将当前bean放入三级缓存
    			addSingletonFactory(beanName, new ObjectFactory<Object>() {
    				@Override
    				public Object getObject() throws BeansException {
    					return getEarlyBeanReference(beanName, mbd, bean);
    				}
    			});
    		}
    		// 初始化bean
    		Object exposedObject = bean;
            //为当前bean serviceAA赋值
    			populateBean(beanName, mbd, instanceWrapper);
    		if (earlySingletonExposure) {
    			Object earlySingletonReference = getSingleton(beanName, false);
    			}
    				
    		return exposedObject;
    	}
    
    
    protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    		Assert.notNull(singletonFactory, "Singleton factory must not be null");
            //将当前bean serviceAA放入三级缓存,key为beanname value为创建该bean的工厂
    		synchronized (this.singletonObjects) {
    			if (!this.singletonObjects.containsKey(beanName)) {
    				this.singletonFactories.put(beanName, singletonFactory);
    				this.earlySingletonObjects.remove(beanName);
    				this.registeredSingletons.add(beanName);
    			}
    		}
    	}
    
    
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {
            //获取当前bean sercieAA所有的属性
    		PropertyValues pvs = mbd.getPropertyValues();
            //......对属性的解析等操作略过
     
            //开始注入属性
    		applyPropertyValues(beanName, mbd, bw, pvs);
    	}
    
    
    protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
        
       //封装所有属性的集合,略过
    	List<PropertyValue> original;
     
        for (PropertyValue pv : original) {
    		String propertyName = pv.getName(); 
    		Object originalValue = pv.getValue();
            //解析引用类型的属性
    		Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
        }
        //应用属性过程略过
    }
    
    public Object resolveValueIfNecessary(Object argName, Object value) {
            //判断是否是运行时bean引用
    		if (value instanceof RuntimeBeanReference) {
    			RuntimeBeanReference ref = (RuntimeBeanReference) value;
                //解析此引用 service BB
    			return resolveReference(argName, ref);
    		}
    
    
    private Object resolveReference(Object argName, RuntimeBeanReference ref) {
     
        String refName = ref.getBeanName();
        refName = String.valueOf(doEvaluate(refName));
        //开始递归调用getbean方法,当前bean为serviceBB
        Object bean = this.beanFactory.getBean(refName);
     
    }
    
    
    • 此时serviceBB开始递归调用getBean()方法,开始重复上述流程,关注流程第五步。此时bean serviceBB实例化完成,并且开始为属性赋值,发现有一个属性为serviceAA。于是尝试获取serviceAA。

    • 进入this.beanFactory.getBean()方法。进入doGetBean()方法。后进入getSingleton(String beanName, boolean allowEarlyReference)

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
            //一级缓存中是否存在当前bean(serviceAA),此时为null
            //isSingletonCurrentlyInCreation(beanName),当前bean是否被标记为
            //正在创建,当前为true,进入判断
    		Object singletonObject = this.singletonObjects.get(beanName);
    		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    			synchronized (this.singletonObjects) {
                    //判断二级缓存中是否有bean serviceAA,当前返回null
    				singletonObject = this.earlySingletonObjects.get(beanName);
    				if (singletonObject == null && allowEarlyReference) {
                    //通过beanname获得了之前在三级缓存中添加的创建serviceAA的工厂方法
    					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
    					if (singletonFactory != null) {
                            //此时singletonObject指向之前实例化完成的serviceAA对象
    						singletonObject = singletonFactory.getObject();
                            //将serviceAA添加到二级缓存中,并从三级缓存中删除
    						this.earlySingletonObjects.put(beanName, singletonObject);
    						this.singletonFactories.remove(beanName);
    					}
    				}
    			}
    		}
    		return (singletonObject != NULL_OBJECT ? singletonObject : null);
    	}
    
    
    • 此时serviceBB的属性赋值完毕,serviceBB的populateBean方法执行结束。其属性service AA指向还未执行完成populateBean()方法的bean serviceAA,等待后续的递归返回。
    protected void addSingleton(String beanName, Object singletonObject) {
    		synchronized (this.singletonObjects) {
                //将serviceBB放入一级缓存
    			this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
                //从三级缓存,二级缓存中删除
    			this.singletonFactories.remove(beanName);
    			this.earlySingletonObjects.remove(beanName);
    			this.registeredSingletons.add(beanName);
    		}
    	}
    
    • 此时serviceBB创建完毕。递归返回继续还未属性赋值完成的bean serviceAA。调用 addSingleton()方法,同上将bean serviceAA放入一级缓存

    总结

    欢迎关注公众号:前程有光,领取一线大厂Java面试题总结+各知识点学习思维导+一份300页pdf文档的Java核心知识点总结!

  • 相关阅读:
    学期总结
    Sprint 2(第一天)
    学期总结
    实验四、主存空间的分配和回收
    阅读《构建之法》与链接有感.
    《构建之法》八、九、十章读后感
    Scrum领取任务
    实验三、进程调度模拟程序实验
    《构建之法》6-7章读后感
    实验二 作业调度模拟程序
  • 原文地址:https://www.cnblogs.com/lwh1019/p/14189142.html
Copyright © 2011-2022 走看看