트러블슈팅
스프링부트에서 @Value는 @RequiredArgsConstructor에 의해 주입받지 못 한다.
기억용블로그
2022. 12. 15. 15:05
728x90
문제 상황
필드 변수를 선언할때 @RequiredArgsConstructor
를 이용하기 위해 항상 하던 것처럼 @Value 변수를 선언할 때에도 private final
로 선언했지만 다음과 같은 에러가 발생했다.
코드
import org.springframework.beans.factory.annotation.Value;
@Slf4j
@Service
@Transactional
@RequiredArgsConstructor
public class Test {
@Value("${email}")
private final String EMAIL;
콘솔 stdout
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
Description:
Parameter 0 of constructor in ai.planit.superb.domain.mail.service.Test required a bean of type 'java.lang.String' that could not be found.
Action:
Consider defining a bean of type 'java.lang.String' in your configuration.
원인
Lombok의 @RequiredArgsConstructor
로 필드의 private final의 컴파일 에러는 해결된 것처럼 보이지만 @Value
가 주입되는 타이밍과 @RequiredArgsConstructor
의 주입 타이밍이 달라 에러가 발생하는 것이 원인으로 보인다.
해결 방법
@RequiredArgsConstructor
annotation을 제거하고 생성자를 통해 일일히 값을 넣어준다.
@Value("${email}")
private final String EMAIL;
public Test(@Value("${email}") String email) {
this.EMAIL = email;
}
하지만 이 방법은 다른 생성자가 늘어날수록 값을 일일히 넣어주어야 하는 불편함이 있다.
- final 키워드를 제거해준다.
문제의 원인은 서로 다른 주입 타이밍을 가지는 라이브러리간의 충돌로 인해 발생하는 것이므로 Lombok을 통해 final 생성자를 생성하도록 만들고 @Value는 Lombk을 거치지 않도록 설정한다.
@Value("${email}")
private String EMAIL;