spring dependency injection (1)

💻 Programming

스프링 의존성 주입(DI)

스프링 의존성 주입 (Spring Dependency Injection)

스프링에서 의존성을 주입하는 방법은 현재 세 가지가 있습니다.

첫 번째는 생성자 주입 방식이고 두 번째는 Setter 주입 방식, 그리고 마지막으로 Field 주입 방식이 있습니다.

순서대로 한번 보도록 하겠습니다.

 

1. 생성자 주입 (Constructor Based Dependency Injection)

말 그대로 생성자에 @Autowired로 다른 빈을 주입하는 방식입니다.

@Controller
public class MyController {
    private MyService myService;
 
    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }
}

주입해야하는 빈이 많을 경우 생성자 자체가 커지게 됩니다. 그런경우 만약 lombok 을 사용한다면 아래처럼 작성할 수 있습니다.

@Controller
@RequiredArgsConstructor
public class MyController {

    private final MyService myService;
 
}

@RequiredArgsConstructor 어노테이션을 class 레벨에 붙여주고 주입할 빈은 final 키워드를 붙여주면 lombok에서 자동으로 생성자 주입을 이용하여 빈들을 주입해줍니다. 필요한 빈들은 모두 final 키워드를 붙여서 필드로 추가만 해주면 되죠. 

2. Setter 주입 (Setter Based Dependency Injection)

Setter 메서드를 이용하여 주입하는 방식이죠. 

@Controller
public class MyController {

    private MyService myService;
    
    @Autowired
    public void setMyService(MyService myService) {
        this.myService = myService;
    }
}

특이한 경우를 제외하고는 이 방식은 거의 사용하는 것을 못봤네요

3. Field 주입 (사용하지 마세요)

예전부터 많이 사용되는 방식입니다. 하지만 스프링에서 권고하지 않는 방식이기도 하죠. 

@Controller
public class MyController {

    @Autowired
    private MyService myService;
}

필드 주입 방식은 공식문서에도 소개조차 하고있지 않습니다. 공식문서에는 두 가지 방식만 있다고 설명합니다. 생성자 주입 방식과 setter 주입방식이죠. 그 이유는 필드 주입을 사용하게되면 순환참조 문제를 우회할 수 있게되어 순환참조를 고려하지 않고 개발을 하게되고, 그렇게 설계된 클래스는 하나 이상의 기능을 하게되어 하나의 책임만 가져야 한다는 Single Responsibility 원칙에 위배될 가능성이 높아지게되죠. 또 다른 여러 단점들에 대해서 stackoverflow를 참고하시면 좋을 것 같습니다. 만약 필드 주입을 사용하고 계시다면 생성자 주입 방식으로 바꿔주세요. 그러면 순환참조를 찾아낼 수 있고 순환참조 고리 안에 있는 클래스들을 살펴보면 Single Responsibility 원칙을 위배하는 클래스가 보일겁니다. 그런 것들은 클래스 분리를 통해 개선해주시면 됩니다.

 

 

 

 

 

참고문서

docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependencies

stackoverflow.com/questions/39890849/what-exactly-is-field-injection-and-how-to-avoid-it