1. 实例化BeanA
2. BeanA在属性注入阶段从容器里面找BeanB
3. 如果BeanB已经在容器里面创建好,那万事大吉,没循环依赖的题目
4. 如果BeanB还没有在容器里面创建好,这时间Spring会创建BeanB
5. 创建BeanB的时间又发现依赖BeanA,但此时BeanA也没有创建完,在没有开启循环依赖开关的情况下就会报错:Requested bean is currently in creation: Is there an unresolvable circular reference?
从软件代码分层结构来讲,如果分层公道,这种情况一般可以避免掉,但是避免不了同一个层次中的Bean相互引用,好那既然循环依赖肯定会出现,我们自己先来思考下,如果是我们自己写一个IOC容器,这个题目如何办理?
如何办理循环依赖?
/** * Extension of the {@link InstantiationAwareBeanPostProcessor} interface, * adding a callback for predicting the eventual type of a processed bean. * * <p><b>NOTE:</b> This interface is a special purpose interface, mainly for * internal use within the framework. In general, application-provided * post-processors should simply implement the plain {@link BeanPostProcessor} * interface or derive from the {@link InstantiationAwareBeanPostProcessorAdapter} * class. New methods might be added to this interface even in point releases. * * @author Juergen Hoeller * @since 2.0.3 * @see InstantiationAwareBeanPostProcessorAdapter */public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor { default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException { return bean; }}
复制代码
从类注释中”This interface is a special purpose interface, mainly for internal use within the framework“可以看到,这个接口仅仅是Spring内部为相识决某些题目提供的接口,并不渴望袒露给上层用户使用,所以我们在实际工作中一般用不到的
但是我们要特别注意一个坑: 我们知道在Bean后置处理接口BeanPostProcessor中也有可能返回代理对象,如果这里返回的对象和循环依赖暴袒露去的对象不一致的话就会报以下错误:
Error creating bean with name 'serviceA': Bean with name 'serviceA' has been injected into other beans [serviceB] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'serviceA': Bean with name 'serviceA' has been injected into other beans [serviceB] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example. at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:622) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:514) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:321) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:319) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:866) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) at test.circle_ref.CircleRefTests.run(CircleRefTests.java:13)