봄철 순환 의존성
봄은 이를 어떻게 해결합니까?콩 A는 콩 B에 의존하며 콩 B는 콩 A에 의존합니다.
스프링 참조 매뉴얼에서는 순환 종속성이 어떻게 해결되는지 설명합니다.콩은 먼저 인스턴스화 된 후 서로 주입된다.
다음 클래스를 고려합니다.
package mypackage;
public class A {
public A() {
System.out.println("Creating instance of A");
}
private B b;
public void setB(B b) {
System.out.println("Setting property b of A instance");
this.b = b;
}
}
비슷한 클래스 ★★★★★★★★★★★★★★★★★★★★★★★★★★★」B
:
package mypackage;
public class B {
public B() {
System.out.println("Creating instance of B");
}
private A a;
public void setA(A a) {
System.out.println("Setting property a of B instance");
this.a = a;
}
}
이 컨피규레이션파일이 있는 경우:
<bean id="a" class="mypackage.A">
<property name="b" ref="b" />
</bean>
<bean id="b" class="mypackage.B">
<property name="a" ref="a" />
</bean>
이 설정을 사용해 콘텍스트를 작성하면, 다음의 출력이 표시됩니다.
Creating instance of A
Creating instance of B
Setting property a of B instance
Setting property b of A instance
<> 님의 경우:a
주입되다b
,a
가 아직 완전히 초기화되지 않았습니다.
다른 답변들이 말했듯이, 스프링은 단지 콩을 만들고 필요에 따라 주입하면서, 그것을 처리한다.
그 결과 중 하나는 빈 주입/속성 설정이 XML 배선 파일이 암시하는 것과 다른 순서로 발생할 수 있다는 것입니다.따라서 속성 설정기는 이미 호출된 다른 설정기에 의존하는 초기화를 수행하지 않도록 주의해야 합니다.을 시행하고 입니다.InitializingBean
인터페이스입니다. 하려면 '실행하다'를 해야 합니다.afterPropertiesSet()
되어 있는지 합니다.)(중요한 속성이 실제로 설정되어 있는지 확인하기 위한 코드도 첨부합니다.)
현재 사용하고 있는 코드 베이스(100만 행 이상의 코드)에서는, 기동 시간이 60초 정도로 긴 것에 문제가 있었습니다.12000+ Factory Bean Not Initialized를 받았습니다.예외입니다.
Abstract Bean Factory #doGet Bean에서 조건부 브레이크 포인트를 설정했습니다.
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
경우, 「」는 행해집니다.destroySingleton(beanName)
조건부 중단점 코드를 사용하여 예외를 인쇄했습니다.
System.out.println(ex);
return false;
이것은 FactoryBeans가 순환 의존관계 그래프에 관여하고 있는 경우에 발생합니다.Application Context Aware와 Initializing Bean을 구현하고 콩을 수동으로 주입하여 해결했습니다.
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
public class A implements ApplicationContextAware, InitializingBean{
private B cyclicDepenency;
private ApplicationContext ctx;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
ctx = applicationContext;
}
@Override
public void afterPropertiesSet() throws Exception {
cyclicDepenency = ctx.getBean(B.class);
}
public void useCyclicDependency()
{
cyclicDepenency.doSomething();
}
}
이것에 의해, 기동 시간이 약 15초로 단축되었습니다.
그러므로 봄이 여러분을 위해 이러한 참고 자료를 해결하는 데 도움이 될 수 있다고 항상 생각하지 마세요.
따라서 Abstract Refreshable Application Context #set을 사용하여 주기적인 의존관계 해결을 비활성화할 것을 권장합니다.AllowCircularReferences(false)를 사용하여 향후 많은 문제를 방지합니다.
문제 ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
// 원인: org.springframework.콩류.Bean Current In Creation(빈 현재 생성)예외:이름이 'A'인 콩을 만드는 중 오류 발생: 요청된 콩을 현재 만드는 중입니다.해결할 수 없는 순환 참조가 있습니까?
해결책 1 ->
Class A {
private B b;
public A( ) { };
//getter-setter for B b
}
Class B {
private A a;
public B( ) { };
//getter-setter for A a
}
솔루션 2 ->
Class A {
private final B b; // must initialize in ctor/instance block
public A(@Lazy B b) { this.b = b };
}
Class B {
private final A a; // must initialize in ctor/instance block
public B(A a) { this.a = a };
}
★★★★★★★★★★★★★★★★★★★★★★★★★★★은 일시에 나타나다.a
★★★★★★★★★★★★★★★★★」b
는 (세터 방식을 사용하여) 각각에 주입합니다.
문제가 뭐죠?
예를 들어, A가 B에 의존한다고 가정하면, 스프링은 먼저 A를 인스턴스화한 다음 B를 위해 속성을 설정하고 B를 A로 설정합니다.
하지만 만약 B도 A에 의존한다면?
스프링은 A가 구축(시공자 실행)되었지만 완전히 초기화되지 않은(모든 주입이 완료된 것은 아님) 것을 알게 되었습니다만, A가 완전히 초기화되지 않은 것은 괜찮습니다.현재로서는 이 미초기화된 A 인스턴스를 B로 설정합니다.B가 완전히 초기화 된 후 A로 설정되었고, 마지막으로 A가 완전히 초기화되었습니다.
즉, A를 B에게 미리 노출시키는 것입니다.
컨스트럭터를 통한 의존관계에 대해서는 Sprint는 Bean Current In Creation만 슬로우합니다.예외: 이 예외를 해결하려면 constructor-arg 방식으로 다른 사람에 의존하는 bean에 대해 lazy-init을 true로 설정합니다.
스프링 레퍼런스:
당신은 일반적으로 스프링이 옳은 일을 할 것이라고 믿을 수 있다.컨테이너 로드 시 존재하지 않는 콩에 대한 참조 및 순환 종속성 등의 구성 문제를 검출합니다.스프링은 속성을 설정하고 빈이 실제로 생성될 때 가능한 한 늦게 종속성을 해결합니다.
봄의 순환 의존성 : 콩과 콩의 의존성. Bean A → Bean B → Bean A
솔루션:
@Lazy
★★- 클래스 의존성 재설계
- 세터/필드 주입 사용
@PostConstruct
★★
Spring 컨테이너는 Setter 기반 순환 종속성을 해결할 수 있지만 런타임 예외인 BeanCurrentInCreation을 제공합니다.생성자 기반 순환 종속성의 경우 예외입니다.세터 기반의 순환 의존성의 경우 IOC 컨테이너는 주입 전에 콜라보링 빈을 완전히 구성하는 일반적인 시나리오와 다르게 처리합니다.예를 들어 Bean A가 Bean B에 의존하고 Bean B가 Bean C에 의존하는 경우 용기는 B에 주입하기 전에 C를 완전히 초기화하며 B가 완전히 초기화되면 A에 주입됩니다.그러나 순환 의존성의 경우, 콩 중 하나가 완전히 초기화되기 전에 다른 콩에 주입됩니다.
여기에 명확하게 설명되어 있습니다.Eugen Paraschiv 덕분이다.
순환 의존성은 설계상의 냄새입니다.고정하거나 의존성에 대해 @Lazy를 사용하여 문제를 해결합니다.
일반적으로 컨스트럭터-인젝션을 사용하여 속성인젝션으로 전환하지 않을 경우 Spring의 lookup-method-injection을 사용하면 한 빈이 다른 빈을 쉽게 검색할 수 있으므로 순환 의존관계를 회피할 수 있습니다.여기를 참조해 주세요.http://docs.spring.io/spring/docs/1.2.9/reference/beans.html#d0e1161
스프링 콩 사이에 순환 종속성이 있으면 생성자 주입이 실패합니다.이 경우 Setter 주입은 문제를 해결하는 데 도움이 됩니다.
기본적으로 Constructor Injection은 필수 의존관계에서 유용합니다.옵션 의존관계에서는 재인젝션을 실행할 수 있기 때문에 Setter Injection을 사용하는 것이 좋습니다.
두 개의 콩이 서로 종속되어 있는 경우 두 콩 정의 모두에서 Constructor injection을 사용하지 마십시오.대신에 우리는 콩 중 하나에 세터주사를 사용해야만 한다.(물론 setter injection n 두 bean 정의 모두 사용할 수 있지만, 양쪽 srow 'Bean Current In Creation'에서 컨스트럭터 injection을 사용할 수 있습니다.예외'
"https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources-resource"에서 스프링 문서를 참조하십시오.
또,@Lazy
주석
@Component
public class ClassA {
private ClassB classB;
public ClassB getClassB() {
return classB;
}
@Lazy
@Autowired
public void setClassB(ClassB classB) {
this.classB = classB;
}
}
@Component
public class ClassB {
private ClassA classA;
@Autowired
public ClassB(ClassA classA) {
super();
this.classA = classA;
}
public ClassA getClassA() {
return classA;
}
public void setClassA(ClassA classA) {
this.classA = classA;
}
}
언급URL : https://stackoverflow.com/questions/3485347/circular-dependency-in-spring
'programing' 카테고리의 다른 글
javascript에서 소수점 2자리 float를 해석하는 방법은? (0) | 2022.09.12 |
---|---|
사용자 'root'@'localhost'에 대한 액세스가 거부되었습니다(암호: YES 사용). 권한이 없습니다. (0) | 2022.09.12 |
transition-group 속성 또는 소품 설정 방법 (0) | 2022.09.12 |
Guice의 Assisted 사용방법주사? (0) | 2022.09.12 |
2개의 열이 있는 SQL:상위 3명의 사용자로부터의 커미션 및 커미션 합계 (0) | 2022.09.12 |