<< CTO는 무슨 일을 하나? | Home

Spring에서 Field Injection보다 Constructor Injection이 권장되는 이유

이 주제는 좀 묵은 주제이기도 하지만, 주변을 둘러봐도 그렇지만, 일단 의존성 추가나 삭제가 간결하고 코드량도 많지 않고, 문제 발생한 경우도 없어서인지 Field Injection을 많이 사용하게 됩니다.
하지만 왜 Spring Team에서 Constructor Injection을 추천하는지 리마인드 차원에서 정리해 봅니다.

Spring의 Dependency Injection

1. Constructor Injection
Spring 4.3에서 단일 생성자의 경우 @Autowired가 필요가 없다.
@Component
public class ConstructorInjection {
     private final LoginService loginService;
     private final SignupService signupService;

    @Autowired
    public ConstructorInjection(LoginService loginService, 
                SignupService signupService) {
         this.loginService = loginService;
         this.signupService = signupService;
    }
}

2. Field Injection
@Component
public  class FieldInjection {
    @Autowired
    private LoginService loginService;
    @Autowired
    private SignupService signupService;
}

3. Setter Injection
@Component
public  class SetterInjection {
     private LoginService loginService;
     private SignupService signupService;

    @Autowired
    public  void setLoginService(LoginService loginService) {
         this.loginService = loginService;
    }

    @Autowired
    public  void setSignupService(SignupService signupService) {
         this.signupService = signupService;
    }
}

왜 Constructor Injection을 권장하나?

1. 단일 책임의 원칙
생성자의 인자가 많을 경우 코드량도 많아지고, 의존관계도 많아져 단일 책임의 원칙에 위배된다. 그래서 Constructor Injection을 사용함으로써 의존관계, 복잡성을 쉽게 알수 있어 리팩토링의 단초를 제공하게 된다.

2. 테스트 용이성
DI 컨테이너에서 관리되는 클래스는 특정 DI 컨테이너에 의존하지 않고 POJO여야 한다. DI 컨테이너를 사용하지 않고도 인스턴스화 할 수 있고, 단위 테스트도 가능하며, 다른 DI 프레임 워크로 전환할 수도 있게 된다.

3. Immutability
Constructor Injection에서는 필드는 final로 선언할 수 있다. 불변 객체가 가능한데 비해 Field Injection은 final는 선언할 수 없기 때문에 객체가 변경 가능한 상태가 된다.

4. 순환 의존성
Constructor Injection에서는 멤버 객체가 순환 의존성을 가질 경우 BeanCurrentlyInCreationException이 발생해서 순환 의존성을 알 수 있게 된다.

5. 의존성 명시
의존 객체 중 필수는 Constructor Injection을 옵션인 경우는 Setter Injection을 활용할 수 있다.

Lombok을 활용한 Constructor Injection

참고로 개발 편이성은 좋아질 수 있으나, 의존관계의 복잡성을 명확하게 보여주진 못하게 된다.
@RequiredArgsConstructor는 초기화 되지 않은 final 필드를 매개 변수로 취하는 생성자를 생성하고 @NonNull이 필드는 null 체크가 실행되고 파라미터가 null인 경우는 NullPointerException을 발생시킨다.

1. Spring 4.3 이상
@RequiredArgsConstructor
@Component
public class ConstructorInjection {
    @NonNull
    private final LoginService loginService;
    @NonNull
    private final SignupService signupService;
}

2. Spring 4.3 이전
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Component
public class ConstructorInjection {
    @NonNull
    private final LoginService loginService;
    @NonNull
    private final SignupService signupService;
}

[참고 사이트]
Tags : , ,


Re: Spring에서 Field Injection보다 Constructor Injection이 권장되는 이유

잘 읽고 갑니다~  ^^


Add a comment Send a TrackBack