근데..왜 생성자 주입?

해당 내용은 '스프링 입문을 위한 자바 객체 지향의 원리와 이해'와 인프런 김영한님의 '스프링 핵심 원리 - 기본편' 강의를 참고하였습니다.


자 조금만 생각해보자.

우리는 여태 많은 방법의 의존성 주입방법을 배웠다.

근데 우리가 주로 사용하는건 항상 생성자 주입이다.

왜 생성자 주입을 주로 사용하게 될까?

그 이유는 다음과 같다.

1. 불변

  • 대부분 의존관계 주입이 발생하면 어플리케이션 종료까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 불변해야 한다.
  • 수정자 주입(setXXX)을 사용하면, 메서드를 public으로 열어둬야만 한다.(언제나 변할 수 있다..)
  • 생성자 주입은 객체를 생성할 때 딱 한 번만 호출되기에 그 뒤로는 호출될 일이 없다.

2. 누락

예를 들어서 설명해보자.

만약 우리가 기존에 사용하던 FixServiceImpl.java에서 의존성 주입을 생성자가 아닌 수정자로 받고 있었다고 해보자.

FixServiceImpl.java

@Component
public class FixServiceImpl implements FixService {

    private  FuelTank fuelTank;
    private  Transmission transmission;

    @Autowired
    public void setFuelTank(FuelTank fuelTank){
        this.fuelTank = fuelTank;
    }

    @Autowired
    public void setTransmission(Transmission transmission) {
        this.transmission = transmission;
    }

	...

자 이제 이 상태에서 순수한 자바 코드로 이루어진 테스트를 작성해보자.

FixServiceImplTest.java

class FixServiceImplTest {
    
    @Test
    void test(){
        FixServiceImpl fixService = new FixServiceImpl();
        fixService.getFixCost();
    }

}

코드를 작성했을 때 아무런 이슈도 없고, 실행도 잘 된다.

그러나 결과는?

java: constructor FixServiceImpl in class hello.core.carTest.fix.FixServiceImpl cannot be applied to given types;
  required: no arguments
  found: hello.core.carTest.tank.FuelTank,hello.core.carTest.transmission.Transmission
  reason: actual and formal argument lists differ in length

의존 관계 주입이 누락되었다고 나온다.

그러나 만약 우리가 수정자(Setter)대신에 생성자를 사용했다면 어떻게 될까?

FixServiceImpl.java

public class FixServiceImpl implements FixService {

    private FuelTank fuelTank;
    private Transmission transmission;

//    @Autowired
//    public void setFuelTank(FuelTank fuelTank){
//        this.fuelTank = fuelTank;
//    }
//
//    @Autowired
//    public void setTransmission(Transmission transmission) {
//        this.transmission = transmission;
//    }

        @Autowired
    public FixServiceImpl(FuelTank fuelTank, Transmission transmission) {
        this.fuelTank = fuelTank;
        this.transmission = transmission;
    }

이미지 처럼 바로 문제 있다고 나온다.

테스트 코드에서도 문제 있다고 지적한다.

생성자 주입을 사용하면 주입해야하는 데이터를 누락하면 컴파일 에러가 바로 발생한다.

3. final

생성자를 사용하면, final 을 사용할 수 있다.

이는 1번 불변과 비슷한 맥락의 이야기로, 생성자 주입을 한 번 받으면 바뀌지 않는다.

즉, 생성자에서만 값을 세팅할 수 있다는 것이다.

그리고 final 키워드를 넣으면, 생성자에 값이 설정되지 않았을 때 컴파일 에러를 발생시켜준다.

참고 : 생성자 주입방식이외의 모든 주입 방식은 생성자 이후에 호출되므로, final을 사용할 수 없다.


ps. 컴파일 에러는..최고야

좋은 웹페이지 즐겨찾기