제어의 역전 IoC(Inversion of Control)
개발할 때, 항상 신경 쓰는 것이 낮은 결합도와 높은 응집도이다.
스프링은 제어의 역전(Inversion of Control)을 통해 구성하는 객체 간 느스한 결합, 낮은 결합도를 유지한다.
IoC가 적용되지 않은 상황과 IoC가 적용된 상황을 그림으로 표현하였다.
IoC가 적용되기전에는 필요한 객체의 생성이나 객체와 객체 사이의 으존관계를 개발자가 직접 처리해야한다.
이런 상황에서는 반드시 코드를 수정해야 한다.
하지만 IoC가 적용되면 객체 생성을 개발자가 코드로 직접 하는 것이 아니라 컨테이너가 대신 처리한다.
그리고 객체와 객체 사이의 의존관계 역시 컨테이너가 처리한다.
결과적으로 소스에 의존관계가 명시되지 않으므로 결합도가 떨어져서 유지보수가 쉽다.
클래스 A에서 B객체를 생성하는 예
public class A {
b = new B(); // 클래스 A에서 new 키워드로 클래스 B의 객체 생성
}
스프링 컨테이너에서 객체를 관리하는 예
public class A{
private B b; // 코드에서 객체를 생성하지 않음, 어디선가 받아온 객체를 b에 할당
}
의존성 주입 DI(Dependency Injection)
Dependency injection은 객체 사이의 의존관계를 스프링 설정 파일에 등록된 정보를 바탕으로 컨테이너가 자동으로 처리해 준다. 따라서 의존성 설정을 바꾸고 싶을 때 프로그램 코드를 수정하지 않고 스프링 설정 파일 수정만으로 변경사항을 적용할 수 있어서 유지보수 향상 된다.
의존관계 주입은 크게 4가지 방법이 있다.
- 생성자 주입
- 수정자 주입(setter 주입)
- 필드 주입
생성자 주입
- 특징
- 생성자 호출시점에 딱 1번만 호출되는 것이 보장된다.
- 불변, 필수 의존관계에 사용
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
생성자가 1개만 있으면 @Autowired를 생략해도 자동 주입 된다. 물론 스프링 빈에만 해당한다.
수정자 주입(setter 주입)
- 특징
- 선택, 변경 가능성이 있는 의존관계에 사용
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
필드 주입
- 특징
- 코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점이 있다.
- DI 프레임워크가 없으면 아무것도 할 수 없다.
- 사용하지말자!
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
@Bean
OrderService orderService(MemberRepository memberRepoisitory, DiscountPolicy
discountPolicy) {
return new OrderServiceImpl(memberRepository, discountPolicy);
}
일반 메서드 주입
- 특징
- 한번에 여러 필드를 주입 받을 수 있다.
- 일반적으로 잘 사용하지 않는다.
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicydiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
'Spring' 카테고리의 다른 글
[Spirng] HTTP 요청 파라미터 - @ModelAttribute (0) | 2024.05.20 |
---|---|
[Spring] HTTP 요청 파라미터 - @RequestParam (0) | 2024.05.20 |
[Spring] HTTP 요청 파라미터 - 쿼리 파라미터, HTML Form (0) | 2024.05.17 |
[Spring] HTTP 요청 - 기본, 헤더 조회 (0) | 2024.05.17 |
[Spring] 로깅(logging)에 대해 간단히 알아보기 (0) | 2024.05.02 |