循坏依赖指的是,A对象中持有B对象的引用,而B对象中持有A对象的引用,他们之间形成了循环依赖。或者是多个对象之间A依赖于B,B依赖于C,C又依赖A,形成循环依赖。又或者是对象自己依赖于自己。
在spring中实际上是使用三级缓存来解决循环依赖的,spring中的三级缓存分别是
private final MapsingletonObjects = new ConcurrentHashMap<>(256); private final Map earlySingletonObjects = new ConcurrentHashMap<>(16); private final Map > singletonFactories = new HashMap<>(16);
创建两个循环依赖的对象
@Component public class A { @Autowired private B b; }
@Component public class B { @Autowired private A a; }
spring中遇到循环依赖对象的创建步骤
1.在创建A对象时会先创建一个ObjectFactory工厂类
2.调用populateBean向A对象中注入属性
具体代码如下(AbstractAutowireCapableBeanFactory抽象类中的方法)
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { ...... boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //向第三级缓存中添加一个,ObjectFactory工厂类 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } Object exposedObject = bean; try { //向对象中注入属性 populateBean(beanName, mbd, instanceWrapper); exposedObject = initializeBean(beanName, exposedObject, mbd); } catch (Throwable ex) { if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) { throw (BeanCreationException) ex; } else { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex); } } ...... }
3.在注入属性时会在容器中寻找B对象但是没有找到B对象,则开始B对象的创建流程
4.在B对象的创建过程中同样会调用上面代码中的populateBean方法向B对象中A对象
5.这时候会调用getBean方法获取A对象
@Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }
6.在获取A对象的时候会从缓存中尝试获取,这时候从三级缓存中可以获取到A对象的工厂
protectedT doGetBean( String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException { String beanName = transformedBeanName(name); Object beanInstance; // 这个方法里面就会创建A对象并且放入第二级缓存中 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null); } ...... } protected Object getSingleton(String beanName, boolean allowEarlyReference) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { 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 ObjectFactory> singletonFactory = this.singletonFactories.get(beanName); if (singletonFactory != null) { //创建A对象 singletonObject = singletonFactory.getObject(); //将A对象放入第二级缓存中 this.earlySingletonObjects.put(beanName, singletonObject); //将第三级缓存中的A对象的ObjectFactory移除 this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }
以上就是spring中解决循环依赖的方法
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)