Dependency (의존) ?
A가 B에 의존하고 있는 상태일 때, B에 변화가 일어나면 그 변화가 A에도 영향을 미치는 것
class Chef {
private Recipe recipe = new Recipe();
public Chef() {
this.recipe.cook();
}
}
흔히 드는 예시 중 하나
요리사는 레시피에 의존
따라서 레시피가 바뀌면 요리사의 행위도 변화
Chef 객체는 Recipe객체를 생성하고, 그 객체가 가지고 있는 cook이라는 메소드를 활용
만약 Recipe가 하나가 아니라 여러개가 존재하고, Recipe를 추가, 수정, 삭제하고 싶다면 해당하는 객체에 대한 코드를 추가, 수정, 삭제 필요
>> 코드 결합도가 높아지게 되어 코드 재활용성 등 문제 발생
의존성 주입을 사용하는 이유
Dependency Injection 사용
public class Recipe {...}
public class Pizza extends Recipe{...}
public class Chicken extends Recipe {...}
class Chef {
private Recipe recipe = new Recipe();
public Chef(Recipe recipe) {
this.recipe = recipe;
}
public startCook(){
this.recipe.cook();
}
}
Chef 객체에 Recipe라는 객체를 주입해서 사용
Pizza, Chicken 등 다른 레시피를 요리하고 싶다면 해당 요리의 객체를 Chef객체에 넘겨주어 생성
하나의 코드를 계속해서 재사용 가능
DI의 장점
1. 코드의 재활용성 증가
2. 객체 사이의 의존성/종속성 감소
3. 가독성 증대
4. Test 용이
Spirng에서의 DI
Spring은 DI를 편하게 사용하는 방법 3가지 제공
1. 생성자 주입
Contstructor Injection
@Service
public class UserServiceImpl implements UserService{
private UserRepository userRepository;
private UserServiceImpl userService;
@Autowired
public UserServiceImpl(UserRepository userRepository, UserService userService){
this.userRepository = userRepository;
this.userServicer = userService;
}
}
생성자 주입은 생성자 호출 시점에 1번 호출 되는것이 보장
주입받는 객체의 변화가 없거나 반드시 객체의 주입이 필요한 경우에 강제하기 위해 사용 가능
** Spring에서는 생성자가 1개만 있을 경우 @Autowired는 생략 가능
2. 수정자 주입
Setter Injection
Setter를 사용해서 의존 관계를 주입하는 방법
주입 객체가 변할 수 있는 경우에 사용
@Service
public class UserServiceImpl implements UserService{
private UserRepository userRepository;
private UserServiceImpl userService;
@Autowired
public void setUserRepository(UserRepository userRepository){
this.userRepository = userRepository;
}
@Autowired
public void setmUserService(UserService userService){
this.userService = userService;
}
}
@Autowired로 주입 대상이 없는 경우에는 오류 발생 >> Bean에 존재하지 않는 경우
3. 필드 주입
Feild Injection
필드에 의존 관계를 주입하는 방법
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserRepository userRepository;
@Autowired
private UserServiceImpl userService;
}
코드가 간결하기 때문에 과거에 많이 사용되던 방법
But 외부에서 변경이 불가능 >> Test코드에서 Mock데이터를 사용하여 주입 불가
Spring과 같은 DI프레임워크가 존재해야만 사용 가능
생성자 주입을 권장하는 이유
- 객체의 불변성 확보
- Test코드의 작성
- final키워드 작성 및 Lombok 결합
DI를 위한 3가지 방법 중 생성자 주입만이 객체 생성과 동시에 의존성 주입 >> final 변수 할당 가능 !!
나머지 방법은 객체를 우선 생성 => 의존성 주입 함수 호출
순서로 수행되기 때문에 finla 변수 할당 불가능
- 순환참조에러 방지
클라이언트 구동 시, Bean에 등록하기 위해 객체를 생성하는데, 이때 순환참조 발견 시 바로 에러 호출
만약 수정자 주입을 사용한다면 객체 생성 후, 객체에 의존성을 주입하는 순간에 에러 호출되기 때문에 생성만 한 상태에서는 코드가 잘못되었는지 발견하기 힘듬
'끄적 > BE' 카테고리의 다른 글
MVC1 MVC2 (0) | 2023.01.05 |
---|---|
Inversion of Control (제어 반전) (0) | 2023.01.03 |
Persistence Context (영속성 컨텍스트) (0) | 2023.01.01 |
Spring MVC (0) | 2022.12.29 |
JPA, Spring Data Jpa (0) | 2022.12.28 |