Spring framework에서 Bean 주입 시 아래와 같은 내부 코드를 통해 Bean을 찾게되는데,
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
return null;
만약 Bean을 찾지 못하게 되면
Field Injection의 경우에는 해당 field의 값이 null로 들어가게 되어, 결국 runtime 에러가 발생되게 되고
@Autowired
private BeanTestService beanTestService;
public void beanTest() {
// beanTestService에 값이 null이 들어갈 경우, 여기서 NullPointerException이 발생된다.
this.beanTestService.run();
}
Constructor Injection의 경우에는 final 접근자를 사용하기 때문에 Spring context loading 시에 에러가 발생된다.
private final BeanTestService beanTestService;
// 요즘은 보통 Lombok의 @RequiredArgsContructor 어노테이션을 사용하여 생성자 코드를 대체한다.
public BeanTestClass(BeanTestService beanTestService) {
this.beanTestService = beanTestService;
}
public void beanTest() {
// beanTestService에 값이 null이 들어갈 경우, 이미 생성자에서 에러가 발생되기 때문에 여기까지 오지 않는다.
this.beanTestService.run();
}
때문에 Bean 관련 에러가 발생될 때는 해당 프로그램이 실행될 때 에러를 발생시켜 버그를 줄일 수 있게 하기 위해 Constructor Injection이 권장된다.