빈 등록 순환 참조 문제

## 예시 1: 두 Bean이 서로를 주입하는 경우 (A → B, B → A)

가장 대표적인 순환 참조 예시입니다. ServiceAServiceB가 필요하고, ServiceBServiceA가 필요하여 서로를 무한히 기다리는 교착 상태에 빠집니다.

ServiceA.java

@Service
public class ServiceA {

    private final ServiceB serviceB;

    // ServiceA를 만들려면 ServiceB가 필요하다.
    @Autowired
    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}

ServiceB.java

@Service
public class ServiceB {

    private final ServiceA serviceA;

    // ServiceB를 만들려면 ServiceA가 필요하다.
    @Autowired
    public ServiceB(ServiceA serviceA) {
        this.serviceA = serviceA;
    }
}

### Spring 컨테이너의 동작 흐름 (실패 과정)

  1. Spring이 ServiceA Bean을 생성하려고 시도합니다.

  2. ServiceA의 생성자를 보니 ServiceB가 필요합니다.

  3. Spring이 ServiceB Bean을 생성하려고 시도합니다.

  4. ServiceB의 생성자를 보니 ServiceA가 필요합니다.

  5. 하지만 ServiceAServiceB를 기다리고 있으므로 아직 생성이 완료되지 않았습니다.

  6. "A는 B를, B는 A를..." 무한 대기 상태에 빠지며, Spring은 BeanCurrentlyInCreationException을 발생시키고 애플리케이션을 시작하지 못합니다.


## 예시 2: @Configuration이 자신의 Bean을 주입받는 경우 (질문 주신 내용)

이 경우도 "닭이 먼저냐, 달걀이 먼저냐"와 같은 문제입니다.

AppConfig.java

@Configuration
public class AppConfig {

    private final MyService myService; // ◀ 2. MyService를 주입받으려 함

    // AppConfig Bean을 만들려면 myService가 필요
    @Autowired
    public AppConfig(MyService myService) {
        this.myService = myService;
    }

    @Bean // ◀ 1. myService라는 Bean을 여기서 만듦
    public MyService myService() {
        return new MyService();
    }
}

### Spring 컨테이너의 동작 흐름 (실패 과정)

  1. Spring은 @Bean 메서드를 실행하기 위해 먼저 @Configuration 클래스인 AppConfig의 Bean을 생성해야 합니다.

  2. AppConfig의 생성자를 보니 MyService Bean이 필요합니다.

  3. Spring은 MyService Bean을 찾으려고 합니다.

  4. MyService Bean은 AppConfig 안에 있는 myService() 메서드를 실행해야만 만들 수 있습니다.

  5. 하지만 myService() 메서드를 실행하려면 AppConfig Bean이 먼저 생성되어야 합니다.

  6. "AppConfig를 만들려면 MyService가, MyService를 만들려면 AppConfig가..." 역시 순환 참조에 빠져 Bean을 생성할 수 없습니다.

Last updated