DI 방식 3가지
1.
생성자
class BurgerChef {
private BurgerRecipe burgerRecipe;
public BurgerChef(BurgerRecipe burgerRecipe) {
this.burgerRecipe = burgerRecipe;
}
}
Java
복사
2.
필드 객체 선언
@Service
public class StudentService {
@Autowired
private CourseService courseService;
}
Java
복사
3.
setter() 메서드를 이용
@Service
public class StudentService {
private CourseService courseService;
@Autowired
public void setCourseService(CourseService courseService) {
this.courseService = courseService;
}
}
Java
복사
각 장점과 단점
생성자 | 수정자 메서드(setter) | 필드 주입 | |
장점 | • 생성자 호출 시점에 딱 1번만 호출되는 것이 보장
• 주입하는 객체가 누락된 경우 컴파일 시점에 오류 발견 가능 | • 주입 받는 객체가 변경 될 가능성이 있는 경우 수정 편리 | • 코드가 간결 |
단점 | • 런타임 중에 객체가 변경 될 가능성이 매우 드물다. | • 외부에서 접근이 불가하여, 테스트 코드 작성이 어려움
• DI 프레임워크가 존재해야 사용 가능 @Autowired |
생성자 주입을 사용하자!
1.
생성자의 호출 시점에 1회 호출 되는 것이 보장된다.
•
중간에 주입 받은 객체가 변하지 않음
•
수정의 가능성이 없어 변경의 가능성을 배제하고 불변성이 보장된다.
2.
테스트 코드 작성 용이
•
프레임워크에 의존하지 않고 순수한 자바 코드로 단위테스트가 가능하다.
•
예시로, 아래와 같은 필드 주입의 경우
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public void register(String name) {
userRepository.add(name);
}
}
Java
복사
public class UserServiceTest {
@Test
public void addTest() {
UserService userService = new UserService();
userService.register("MangKyu");
}
}
Java
복사
테스트 코드를 이렇게 짜게 되면, 테스트 코드는 Spring 위에서 동작하지 않으므로 의존관계 주입이 되지 않을 것이다. → userRepository가 null임
하지만 생성자 주입 방식은 테스트 시, 생성자 호출 방식을 이용하기 때문에 Spring 없이도 의존 관계 주입이 잘 된다. (단위테스트 가능)
3.
final 키워드 작성 가능
•
다른 주입 방법들은 의존관계가 객체의 생성 이후에 주입되므로
final 키워드를 사용할 수 없지만,
생성자 주입 방식은 컴파일 시점에 누락된 의존성을 확인 가능하므로
final 키워드를 사용할 수 있다.
4.
스프링에 의존적이지 않다.
5.
애플리케이션 구동 시점에 순환 참조 에러 방지가 가능하다.
→ Bean에 등록하기 위해 객체를 생성하는 과정에서 다음과 같이 순환 참조가 발생하기 때문
참고