on
[IoC container, 생성자 주입] JAVA > Spring
[IoC container, 생성자 주입] JAVA > Spring
AppConifg.java (순수자바로 설정 클래스)
public class AppConfig { //memberService는 AppConfig를 통해 불러낸다. //생성자 주입 : 생성자를 통해서 객체를 주입. public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } public MemberRepository memberRepository(){ return new MemoryMemberRepository(); } public OrderService orderService(){ return new OrderServiceImpl(memberRepository(), discountPolicy()); } public DiscountPolicy discountPolicy(){ return new FixDiscountPolicy(); } }
1) AppConfig 자바 클래스에서 설정에 해당하는 부분을 주입한다.
2) MemberRepository를 MemmoryMemberRepository로 주입하는 것을 설정에서 확인 할 수 있다.
3) OrderService를 생성된 memberRepository에서 생성된 MemoryMemberRepository(메모리 레포지토리)로 생성한다.
4) OrderService를 discountPolicy에서 FixDiscountPolicy(정액할인정책)으로 생성한다.
5) memberRepository의 주입을 databaseRepository로 변경하면 손쉽게 레포지토리로 변경이 가능하다.
6) discountPolicy의 주입을 FixDiscountPolicy(정액할인정책) 에서 RateDiscountPolicy(비율할인정책) 로 변경이 가능하다.
MemberServiceImpl.java ( MemberService 인터페이스는 생략 )
MemberServiceImpl.java public class MemberServiceImpl implements MemberService{ private final MemberRepository memberRepository; //MemberServiceImpl 이 repository를 선택하도록 하지 않고 //이 부분을 AppConfig에서 설정하도록 한다. //이렇게 설정하면, 추상화에 대해서만 의존한다. DIP를 만족한다. //생성자를 통해서 어떤 레포지토리를 선택할 지 정한다. public MemberServiceImpl(MemberRepository memberRepository){ this.memberRepository = memberRepository; } @Override public void join(Member member) { memberRepository.save(member); } @Override public Member findMember(Long memberId) { return memberRepository.findById(memberId); } }
1) 멤버에 대한 구현체는 기본적으로 join(회원가입), findMember(회원조회) 의 오버라이드로 구성되어 있으며 해당구현을 위해 memberRepository의 선언이 필요하다.
2) AppConfig가 없었다면, private final MemberRepository memberRepository = new MemoryMemberRepository(); 라는 소스가 들어가야 하지만 AppConfig가 정의됨에 따라 private final MemberRepository memberRepository; 라는 선언과MemberServiceImpl(MemberRepository memberRepository) 생성자를 선택해서 레포지토리를 선택한다.
3) 즉, MemberServiceImpl 클래스에서는 어떤 Repository를 선택할 수 없고, AppConfig.java에서 선택한다.
AppConfig.java (Spring)
Spring, AppConfig.java @Configuration public class AppConfig { //memberService는 AppConfig를 통해 불러낸다. //생성자 주입 : 생성자를 통해서 객체를 주입. @Bean public MemberService memberService(){ return new MemberServiceImpl(memberRepository()); } @Bean public MemberRepository memberRepository(){ return new MemoryMemberRepository(); } @Bean public OrderService orderService(){ return new OrderServiceImpl(memberRepository(), discountPolicy()); } @Bean public DiscountPolicy discountPolicy(){ return new FixDiscountPolicy(); } }
1) 순수 자바로 되어있던 AppConfig.java를 spring 형태의 AppConfig.java로 변경한다.
2) IoC Container에 등록하기 위해, @Configuration, @Bean 어노테이션을 이용하여 설정한다.
TEST CODE (Junit5)
public class MemberServiceTest { MemberService memberService; @BeforeEach public void beforeEach(){ //변경 전 (java) //AppConfig appConfig = new AppConfig(); //memberService = appConfig.memberService(); //Spring 변경 후 ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); memberService = ac.getBean("memberService", MemberService.class); } @Test void join(){ //given Member member = new Member(1L, "memberA", Grade.VIP); //when memberService.join(member); Member findMember = memberService.findMember(1L); //then Assertions.assertThat(member).isEqualTo(findMember); } }
1) IoC컨테이너에 AppConfig으로 @Bean형식으로 등록된 서비스들을 불러온다.
2) java 코드에서는 appConfig를 생성하는 코드를 작성했지만,
3) Spring으로 AppConfig.java 설정이 변경된 후에는 AnnoTationConfigApplcationContext에 등록된 bean으로 서비스를 불러 온 후, 코드를 실행한다.
from http://not-null.tistory.com/69 by ccl(A) rewrite - 2021-12-20 02:01:54