일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 자바
- 오라클
- Oracle
- html
- jsp
- ERWin
- DB
- squery
- Project
- 객체지향
- web
- 객제지향
- 공부
- UI
- 데이터베이스
- 테이블
- 공부를열심히
- 프로젝트
- javascript
- 객체지향프로그래밍
- 프로그래밍
- Java
- 코딩
- 웹프로그래밍
- orcle
- CSS
- 웹
- 객제지향프로그래밍
- 주말이다..
- sql
- Today
- Total
햄찌개
[Spring] DI(Dependency Injection) 의 정의와 사용 본문
스프링 DI 컨테이너 사용 단계
1. DI 모듈 의존성을 설정
2. Spring bean metadata configuration 파일 작성
1) 컨테이너가 관리할 객체(been/빈) 등록
2) 등록된 been들 같의 의존관계 형성 (의존성 주입)
- 생성자 주입(constructor injection) : 필수 전략 주입에 활용.
- setter Injection
3. 어플리케이션의 entry point에서 DI 컨테이너 객체 생성 : 어플리케이션 중 가장 먼저 나와야한다.
4. container가 가진 getBean으로 필요한 객체 주입.
5.컨테이너 close
스프링 컨테이너의 빈 관리 특성
1. Singleton : 특별한 설정(scope)이 없는한 빈을 싱글턴으로 관리
2. 특별한 설정(laze-init)이 없는 한 등록된 빈의 객체가 일시에 생성됨. : true이면 주입시에 생성됨, false면 미리 생성, singleton에서 사용 -> prototype과는 객체 주입시 계속 생성 하는 차이가 있다.
beans에 default-lazy-init 으로 한번에 설정도 가능
3. 객체 생성 순서를 직접 제어하기 위한 솏성 : depends-on이 있으면 먼저 만들어준다.
4. 컨테이너는 빈의 생명주기에 따라 callback 호출 구조를 가짐
스프링 프레임워크의 주요 철학 중 하나로 가장 큰 테두리 중 하나는 DI(Dependency Injection) 이다.
Dependency Injection 에 대해 먼저 살펴보자면, 말그대로 "의존성 주입" 을 말하며, 스프링 프레임워크는 Framework 레벨에서 DI 를 제공해준다.
Spring 의 Container 들은 Bean 객체들을 관리하는 데 있어서 DI 를 이용하며 이를 통해 Life Cycle 을 용이하게 관리할 수 있으며 이 것이 스프링 프레임워크의 핵심적인 동작이라고 할 수 있다.
즉, 프레임워크 레벨의 관리를 통해 개발자는 객체들간의 의존성에 신경을 덜 쓰고 Coupling 을 줄일 수 있으며 높은 재사용성과 가독성있는 코드를 만들어낼 수 있다.
이를 제어의 역전(Inversion Of Control) 이라 하며, 이것이 스프링 프레임워크의 특징적인 개념인 IOC 이다.
(클래스 관리의 주체가 개발자가 아닌 프레임워크라는 뜻이다.)
그리고 결과적으로 이러한 개발 편리성은 높은 생산성을 이끌어낼 수 있는 스프링의 큰 장점이다.
- Dependency Injection 을 통해 얻을 수 있는 장점 -
(1) Dependency Reduction : 객체 상호 간 의존성 관계를 줄여준다.
(2) Reusable Structure : 코드의 재사용과 조합이 용이하다.
(3) Readability : 코드들이 분리되다보니 가독성이 뛰어나진다.
(4) Loose Coupling & Easy to change : 구조는 변화에 민감하지 않을 수 있다.
그 외에 테스트가 용이하고 다양한 패턴을 적용하는 데 유연하다는 점도 큰 장점이 될 수 있다.
Spring Framework 에서 개발자가 Dependency Injection 을 하는 데 몇가지 방법들이 있다.
(1) Field Injection
가장 흔히 볼 수 있는 Injection 방법으로 사용하기도 간편하고 코드도 읽기 쉽다.
public class Sample {
@Autowired
private Example example;
}
많이 사용됨에도 불구하고 Field Injection 을 통한 의존성 주입은 권장되지 않는다.
이유는 너무 추상적인 Injection 기법 때문이다. 의존성 주입이 쉽기 때문에 Dependency 관계가 복잡해질 우려가 있으며 이는 Framework 의 사용에 있어 다음과 같은 안티패턴적 측면을 갖는다.
- Single Responsibility Principle Violation
: 너무나 쉬운 의존성의 주입은 하나의 클래스가 지나치게 많은 기능을 하게됨으로써 초기 설계의 목적성이자 "객체는 그에 맞는 동작만을 한다." 는 원칙에 위배되기 쉽다.
위배된 경우 리팩토링의 비용은 크다.
- Dependency Hiding
: 추상화된 의존관계는 의존성을 검증하기 힘들게 만든다.
- DI Container Coupling
: Field Injection 을 사용하면 해당 클래스를 곧바로 Instant 화시킬 수 없다. 이 부분 때문에 Constructor Injection 이 권장되는 이유이기도 하다.
가령 Container 밖의 환경에서 해당 클래스의 객체를 참조할 때, Dependency 를 정의해두는 Reflection 을 사용하는 방법 외에는 참조할 수 있는 방법이 없다.
DI Framework 는 Field Injection 된 클래스의 Instance 화에 대해서 Null Pointer Exception 을 만들어낼 것이다.
- Immutability
: Field Injection 된 객체는 final 을 선언할 수 없으므로 가변적(Mutable)이다. 객체는 변경될 수 있으며 이에 대한 대응에는 큰 비용이 든다.
(2) Setter Injection
선택적인 의존성을 주입할 경우 유용하며, Spring 3.x 대까지 가장 권장되던 방식이다.
public class Sample {
private Example example;
@Autowired
public void setExample(Example example) {
this.example = example;
}
}
Field Injection 으로 인한 패턴적 위험성을 상당 부분 해소한다. Optional Injection 의 경우 권장되는 방식이다.
@Required 어노테이션을 이용하면 의존성이 필요한 Setter 를 만들 수 있다.
(3) Constructor Injection
Spring 4.x 이상부터 권장되는 방식이다.
public class Sample {
private final Example example;
@Autowired
public Sample(Example example) {
this.example = example;
}
}
코드를 통해 알 수 있듯, final 선언이 가능하며 Immutability 에 대한 해소가 가능하며 의존성의 순환 참조(Circular Dependency) 에 대한 예방이 가능하다.
순환 참조 시 위의 방법을 이용한 코드는 BeanCurrentlyCreationExeption 을 발생시킨다.
역시 위에서 언급된 Container Coupling 문제도 해결이 되는데, 생성자를 통한 Injection 이므로 즉각적인 Instance 화 등에 대한 문제도 해결된다.
많은 예제 코드들이 Field Injection 방식을 사용하고 있으나 Constructor Injection 의 사용이 권장된다.
추가로 참조한 바에 의하면 Spring Team 에서는 Setter 방식을 좀 더 권장하며 이유는 생성자가 지나치게 복잡해질 수 있기 때문이라고 한다.
패턴적 관점에서 이견이 있는 듯 하다.
Spring 4.3 이상부터는 생성자가 하나인 경우 @Autowired 를 사용하지 않아도 무방하다.
정리에 있어 다음 링크들을 참조하였다.
https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/
https://dzone.com/articles/dependency-injection-pitfalls
https://blog.outsider.ne.kr/753
'웹기반어플리케이션' 카테고리의 다른 글
[Spring] Annotation 활성화 (0) | 2021.01.07 |
---|---|
[Java] Call by value와 Call by reference (0) | 2021.01.06 |
[Spring] Annotation 종류와 기능 (0) | 2021.01.06 |
lombok (0) | 2021.01.06 |
Spring Bean Scope (0) | 2021.01.06 |