Step11. DI의 3가지 주입 방법

이신욱·2023년 8월 17일
0

Spring

목록 보기
11/11
post-thumbnail

Step4.DI/IoC에서 DI에 대해 이야기 해본적이 있다.
그리고 크게 3가지 주입방식이 있고, 그중에서 생성자 주입방식이 권장된다고 말했었는데
오늘은 3가지 주입방식의 특징과 생성자 주입방식이 권장되는 이유에 대해서 알아보자.

1. DI의 3가지 방법


  1. 생성자 주입
  2. 필드 주입
  3. Setter 주입

1) 생성자 주입

public class MenuController{

	private final MenuService menuService;
    
    @Autowired
    public MenuController(MenuService menuService){ //생성자
    	this.menuService = menuService;
   }
}
  • 생성자를 통해 DI를 구현하여 객체 생성과 동시에 의존성이 주입된다.
  • 생성자가 1개일 경우 @Autowired를 생략해도 주입이 가능하다.

2) 필드 주입

public class MenuController{
	
    @Autowired
	private MenuService menuService;
}
  • 필드에 @Autowired를 사용하여 자동으로 스프링 빈을 매핑하여 DI를 구현한다.

3) Setter 주입

public class MenuController{

	private final MenuService menuService;
    
    @Autowired
    public setMenuService(MenuService menuService){ //setter
    	this.menuService = menuService;
   }
}
  • setter 메서드에 @Autowired를 사용하여 의존성을 구현한다.

2. 생성자 주입을 권장하는 이유


1) 순환 참조 방지

public class A{
	
    @Autowired
	private final B b;
    
    public void acall(){
    	b.bcall();
	}
}

public class B{
	
    @Autowired
	private final A a;
    
    public void bcall(){
    	a.acall();
	}
}
  • 위 예시는 필드 주입 방식으로 작성되어 있다.
  • A는 B에 의존하고, B는 A에 의존하는 식으로 서로 의존하고있다.
  • A의 acall()은 B의 bcall()을 호출하고, 마찬가지로 B의 bcall()은 A의 acall()을 호출하며
    끝이 없는 호출을 반복하다가 Error를 발생시킬것이다.

이유는?

객체 생성과 의존관계 주입시점이 분리되어있기 때문이다.
따라서 필드주입, setter주입방식은 객체(bean)생성 이후, 의존관계 주입이 수행되고 해당 비즈니스 로직에서 순환 참조가 일어나기 때문에 사전(어플리케이션 구동 시점)에 감지하고 경고할 수 없다.

반면 생성자 주입방식의 경우 생성과 동시에 의존관계 주입이 수행되므로 어플리케이션 구동 시점에 순환참조를 발견할 수 있다.

2) 불변성 확보

생성자 주입은 주입받은 의존성을 클래스 내부에서 변경할 수 없도록 한다.
따라서 클래스의 불변성과 안전성을 보장할 수 있다.(final선언이 가능하다.)

반대로 Setter주입의 경우 setter의 외부 호출로인해 객체가 변경될 가능성이 있다.
의존 관계의 변경이 필요한 경우는 매우 적고, 이 매우 적은 가능성때문에 불필요한 수정의 가능성을 열어두는 것은 SOLID의 OCP(개방폐쇄원칙)을 위반하는것이 된다.

 ocp(개방폐쇄원칙) : 모듈은 확장에는 열려있어야 하고, 변경에는 닫혀있어야 한다.

3) 테스트 용이성

스프링 DI컨테이너에 독립적인 테스트코드를 작성할 수 있다.
main코드가 필드 주입방식으로 작성된 경우 순수한 자바 코드로 unit test하는것은 불가능하다.
main코드는 Spring 프레임워크 위에서 동작하지만 테스트코드는 Junit으로 동작한다.
따라서 필드 주입 방식은 DI컨테이너의 도움 없이는 테스트코드를 작성할 수 없다.

profile
1인분 하는 개발자 되기

0개의 댓글