版本:Spring Framework 5.3.25 GA
循环依赖
If you use predominantly constructor injection, it is possible to create an unresolvable circular dependency scenario.
如果你主要使用构造方法注入,有可能造成无法解析的循环依赖情况。
For example: Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException
.
例如:A类需要通过构造方法注入B类的一个实例,而且B类需要通过构造方法注入A类的一个实例。如果你这样配置beans:类A和类B互相注入对方,Spring IoC容器会在运行时检测到这个循环依赖,抛出异常
BeanCurrentlyInCreationException
。
One possible solution is to edit the source code of some classes to be configured by setters rather than constructors. Alternatively, avoid constructor injection and use setter injection only. In other words, although it is not recommended, you can configure circular dependencies with setter injection.
一个可能的解决方案是,编辑一些类的源代码,用setters配置而不是构造方法。或者,避免使用构造方法注入,只使用setter注入。换句话说,你可以用setter注入来配置循环依赖,即使那是不推荐的。
Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B forces one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken-and-egg scenario).
与典型情况(没有循环依赖)不同,bean A和bean B之间的循环依赖强制其中一个在完全初始化之前被注入到另一个中(一个经典的"先有鸡还是先有蛋"的场景)。
You can generally trust Spring to do the right thing. It detects configuration problems, such as references to non-existent beans and circular dependencies, at container load-time.
你通常可以相信Spring会做正确的事情。Spring在容器加载时检测配置问题,例如对不存在的bean的引用和循环依赖。
Spring sets properties and resolves dependencies as late as possible, when the bean is actually created.
当bean被实际创建时,Spring会尽可能晚地设置属性和解析依赖。
This means that a Spring container that has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies — for example, the bean throws an exception as a result of a missing or invalid property.
这样说的意思是,当你请求一个对象,如果在创建它或它的一个依赖时出问题,被正确启动的Spring容器稍后会生成一个异常——例如,bean由于属性缺少或者无效时会抛出一个异常。
This potentially delayed visibility of some configuration issues is why ApplicationContext
implementations by default pre-instantiate singleton beans.
这种对某些配置问题的可能延迟的可见性,是
ApplicationContext
的实现默认预实例化单例对象的原因。
At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext
is created, not later.
以一些预先的时间和内存为代价在bean被实际需要之前创建它们,你就会发现在
ApplicationContext
被创建时发现配置问题,而不是之后。
You can still override this default behavior so that singleton beans initialize lazily, rather than being eagerly pre-instantiated.
你仍可以重写这个默认的行为,以便单例bean延迟初始化,而不是被急切地预实例化。
If no circular dependencies exist, when one or more collaborating beans are being injected into a dependent bean, each collaborating bean is totally configured prior to being injected into the dependent bean.
如果循环依赖不存在,当一个或多个协作bean被注入到一个依赖bean时,每个协作bean在被注入到依赖bean之前都被完全配置。
This means that, if bean A has a dependency on bean B, the Spring IoC container completely configures bean B prior to invoking the setter method on bean A.
这个的意思是,如果bean A有对bean B的依赖,Spring IoC容器在调用bean A的setter方法之前会完全配置bean B。
In other words, the bean is instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecycle methods (such as a configured init method or the InitializingBean callback method) are invoked.
换句话说,bean被实例化(如果它不是预实例化单例),他的依赖被设置,相关的生命周期方法(例如被配置的初始化方法或者InitializingBean回调方法)被调用。