더보기
- 애플리케이션 실행 시점(런타임)에 외부에서 실제 구현 객체를 생성하고 클라이언트에 전달해서 클라이언트와 서버의 실제 의존관계가 연결 되는 것을 의존관계 주입이라 한다.
- 객체 인스턴스를 생성하고, 그 참조값을 전달해서 연결된다.
- 의존관계 주입을 사용하면 클라이언트 코드를 변경하지 않고, 클라이언트가 호출하는 대상의 타입 인스턴스를 변경할 수 있다.
- 의존관계 주입을 사용하면 정적인 클래스 의존관계를 변경하지 않고, 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.
먼저 코드로 살펴보자.
public class OrderServiceImpl implements OrderService {
private final MemberRepository repository = new MemoryMemberRepository();
//private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
}
주문서비스 클라이언트는 할인정책이 바뀔때 마다 코드를 변경해야 한다. 즉, 추상(인터페이스)뿐만 아니라 구체(구현)클래스에도 의존하고 있다. 클라이언트 코드를 변경해야 하기 때문에, OCP를 위반한다.
그럼 어떻게 문제를 해결할 수 있을까?
DIP를 위반하지 않도록 인터페이스에만 의존하도록 의존관계를 변경하면 된다.
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
//private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
private DiscountPolicy discountPolicy;
}
구현체가 없기 때문에 현 상황에서는 NPE(NullPoniterException)가 발생한다.
각 메소드를 스프링 bean으로 등록하자.
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Component, @Controller, @Service 어노테이션을 붙일 경우 스프링 빈으로 자동 등록된다.
해당 클래스에 생성자로 의존관계 주입을 해준다.
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;
}
생성자에 @Autowired 를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다. 생성자가 1개만 있으면 @Autowired 는 생략할 수 있다.
해당 클래스 필드에 @Autowired를 붙일 경우, 외부에서 변경할 수 없으므로 테스트하기 힘들다. 또한 DI컨테이너가 없으면 아무것도 할 수 없으므로, 사용하지 않는 것이 좋다.
롬복을 적용한 최종 결과 코드
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
'Computer Science > 디자인 패턴' 카테고리의 다른 글
MVC 패턴에 관한 고찰 (0) | 2022.12.02 |
---|---|
@Transactional에 대해 알아보자 (0) | 2021.11.29 |
DTO? Entity? (0) | 2021.11.26 |