5.2 KiB
5.2 KiB
title, source_type, status, related_branches, related_projects, tags, created, status_label
| title | source_type | status | related_branches | related_projects | tags | created | status_label | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| error / spring-configuration-bean-factory-method-not-processed-2026-06-11 | error-note | raw |
|
|
|
2026-06-11 | resolved |
error: spring-configuration-bean-factory-method-not-processed-2026-06-11
Layer:
raw/errors/— 작업 중 마주친 단일 실패·트러블슈팅 기록. 원본은 raw에 영구 보관한다.
Parent / 부모
- raw/branch-notes/feature-outbound-http-client-baseline — D3 활성화 가드(retry enabled + MeterRegistry 부재 → 기동 실패) 테스트 작성 중 발생.
증상 / Symptom
- 에러 메시지 (원문 그대로):
OutboundHttpResilienceConfigTest > application_context_fails_to_start_when_retry_enabled_and_no_meter_registry_bean() FAILED java.lang.AssertionError at OutboundHttpResilienceConfigTest.java:138 - 발생 컨텍스트:
ApplicationContextRunner테스트가assertThat(ctx).hasFailed()를 어서션 — retry enabled + MeterRegistry 부재이므로OutboundHttpResilienceConfig.outboundHttpResilience()가IllegalStateException으로 기동을 실패시켜야 하는데, 컨텍스트가 정상 기동해 버림. - 발생 환경: local, Spring Boot 3.5.14 테스트 (
ApplicationContextRunner). - 재현 가능 여부:
always.
재현 절차 / Reproduction
- 테스트 inner
@Configuration클래스에@Bean OutboundHttpResilienceConfig resilienceConfig() { return new OutboundHttpResilienceConfig(); }처럼 다른 @Configuration 클래스를 @Bean 팩토리 메서드의 반환값으로 등록. ApplicationContextRunner.withUserConfiguration(테스트Config.class).run(...).- 기대:
OutboundHttpResilienceConfig안의@Bean outboundHttpResilience(...)정의가 처리되어 기동 시 IllegalStateException. - 실제: 그
@Bean메서드가 아예 빈 정의로 등록되지 않음 → 가드 코드가 실행되지 않고 컨텍스트 정상 기동 →hasFailed()어서션 실패.
조사 단계 / Investigation log
- 2026-06-11 — 컨텍스트가 실패하지 않는 이유 추적 →
ConfigurationClassPostProcessor는 빈 정의의 클래스가 configuration 후보일 때만@Bean메서드를 처리하는데, 팩토리 메서드 산출물로 등록된 빈은 그 대상이 아님(인스턴스가 단순 빈으로만 등록) →@Configuration클래스는withUserConfiguration(...)등으로 직접 구성 클래스로 등록해야 함. - 2026-06-11 — 테스트 수정:
resilienceConfig()@Bean 메서드 제거 +.withUserConfiguration(RetryEnabledNoMeterConfig.class, OutboundHttpResilienceConfig.class)로 등록, 불필요한@EnableAutoConfiguration도 제거 → 컨텍스트가 기대대로 기동 실패,getStartupFailure().getMessage()에 "MeterRegistry" 포함 확인, green.
근본 원인 / Root cause
- 직접 원인:
@Configuration클래스를 다른 구성 클래스의@Bean팩토리 반환값으로 등록하면 그 안의@Bean메서드들이 빈 정의로 처리되지 않음. - 근본 원인: Spring 의 구성 클래스 처리(
ConfigurationClassPostProcessor)는 "구성 클래스로 등록된 빈 정의"를 스캔 단위로 삼는다 — 팩토리 메서드 산출 인스턴스는 평범한 빈일 뿐 구성 클래스 향상(enhancement)·@Bean 스캔 대상이 아니다. - 트리거 조건: 테스트에서 구성 클래스를 "new 해서 @Bean 으로 돌려주는" 식으로 우회 등록할 때.
Sources / 근거
- 로컬 검증:
OutboundHttpResilienceConfigTest— 수정 전hasFailed()AssertionError / 수정 후 green (./gradlew :adapter-outbound:test). Spring 공식 문서의 해당 절 인용은 미보강 (needs-confirmation— @Configuration javadoc/reference 의 lite mode 절 추가 인용 권고).
해결 / Resolution
- 적용한 조치: 테스트의 구성 등록 방식을
.withUserConfiguration(..., OutboundHttpResilienceConfig.class)직접 등록으로 교체,@Bean팩토리 등록 제거. - 검증 방법:
./gradlew :adapter-outbound:test— 해당 테스트 포함 모듈 전체 green. - 잔여 위험: 없음 (테스트 배선 문제 — 프로덕션 경로는 component-scan 으로 정상 등록).
회고 / Lessons
- 빨리 감지하는 신호: "컨텍스트가 실패해야 하는데 hasNotFailed/정상 기동" + 문제의 @Bean 정의가 컨텍스트에 아예 없음 → 구성 클래스 등록 경로(직접 등록 vs 팩토리 산출물)부터 확인.
- 예방 체크리스트:
ApplicationContextRunner에서 @Configuration 클래스는 항상withUserConfiguration(...)/withConfiguration(...)으로 직접 등록한다. @Bean 으로 돌려주지 않는다. - wiki 일반화 후보: "Spring 구성 클래스는 '등록 방식'이 처리 여부를 결정한다 — 팩토리 산출 @Configuration 의 @Bean 은 죽은 정의" (wiki/concepts 추출 후보).