IoC (Inversion of Control)
- 제어의 역전이라고 불리운다.
- 제어권이 역전 되었다는 뜻이다.
예전에는 의존관계의 제어를 개발자가 직접 해주었다.
그러나 제어권이 컨테이너로 넘어갔고 객체의 생성부터 생명주기의 관리까지 객체에 대한 제어권이 바뀐것을 IoC라고 한다.
IoC 컨테이너란 ?
- 핵심 Interface : BeanFactory
- Application Component 중앙 저장소
- POJO의 생성, 초기화, 서비스, 소멸에 대한 권한을 가짐
- Bean 설정 소스로부터 빈 정의를 읽어들여 빈을 구성하고 제공하는 역할을 한다.
Spring IoC 컨테이너
- ApplicationContext 인터페이스를 구현한 클래스의 오브젝트
- Application Context는 BeanFactory에 여러가지 기능을 추가한 것.
- 빈 인스턴스를 생성
- 의존 관계 설정
- 빈 제공
Bean 등록 과정
Bean은 런타임시점에 ComponentScan이 설정파일들을 읽고 ApplicationContext에 의하여 IoC컨테이너에 등록된다.
DL
Dependency LookUp이라는 뜻으로
클라이언트가 서버에게 자원을 요청할때, 찾는 행위로
객체의 아이디 및 타입을 통해서, Look up 해주는 것을 말합니다.
DI
Dependency Injection이라는 뜻으로
클라이언트가 서버에게 요청한 자원을, 조립할때
클래스 A가 클래스 B를 조립하여 가지고 있어야 하는 경우
객체를 주입을 해줘야 하는데, 이와 같은 행위를 DI라고 합니다.
의존성 주입의 장점
- 의존 관계 설정이 컴파일시가 아닌 실행시에 이루어져 모듈들간의 결합도를 낮출 수 있다.
- 코드 재사용을 높여서 작성된 모듈을 여러 곳에서 소스코드의 수정 없이 사용할 수 있다.
- 모의 객체 등을 이용한 단위 테스트의 편의성을 높여준다.
개발자가 직접 제어
IOC 컨테이너로 부터 DI받는 코드
의존성 주입(DI, Dependency Injection)의 세가지 방법
1. 생성자 주입
현재 가장 권장되고 있는 방법이다. 하나의 생성자가 존재시 기존 Field Injection의 거의 모든 단점을 극복해낸 패턴이다.
필수적으로 사용해야하는 의존성 없이는 인스턴스를 만들지 못하도록 강제할 수 있음.
@Component
public class SampleController {
private SampleRepository sampleRepository;
@Autowired
public SampleController(SampleRepository sampleRepository) {
this.sampleRepository = sampleRepository;
}
}
롬복 이용시
@Service
@RequiredArgsConstructor
public class BoardService {
private final BoardDao boardDao;
}
2. 필드 주입
단일 책임의 원칙 위반
@Autowired 선언 아래 3개든 10개든 막 추가할 수 있으니 말이다. 여기서 Constructor Injection을 사용하면 다른 Injection 타입에 비해 위기감 같은 걸 느끼게 해준다. Constructor의 파라미터가 많아짐과 동시에 하나의 클래스가 많은 책임을 떠안는다는 걸 알게된다.
불변성(Immutability) 보증 x
Constructor Injection과 다르게 Field Injection은 final을 선언할 수 없다. 그래서 객체가 변할 수 있다.
DI 컨테이너의 결합성과 테스트 불편
필요한 의존성을 전달하면 독립적으로 인스턴스화 할 수 있는 단순 POJO가 아님 -> Field Injection을 사용하면 필요한 의존성을 가진 클래스를 곧바로 인스턴스화 시킬 수 없다.
유닛테스트에서 인스턴스화 하여, 각각 나누어서 테스트 x
@Component
public class SampleController {
@Autowired
private SampleRepository sampleRepository;
}
3. Setter 주입 (Method Injection)
Setter Method에 @Autowired를 붙여서 DI를 구현하는 방식
Spring 3.x 버젼에서까지 권장되었지만, 현재는 권장되는 방법은 아니다.
@Component
public class SampleController {
private SampleRepository sampleRepository;
@Autowired
public void setSampleRepository(SampleRepository sampleRepository) {
this.sampleRepository = sampleRepository;
}
}
'Spring' 카테고리의 다른 글
Spring Interceptor (0) | 2021.04.12 |
---|---|
Spring Filter (0) | 2021.04.10 |
Spring AOP (0) | 2021.04.09 |
Spring Filter, Interceptor, AOP 비교 (0) | 2021.04.09 |
Spring 요청의 흐름(Spring MVC 패턴) (0) | 2021.04.09 |