이전에는 AppConfig를 직접 가져와서 DI했지만 이번에는 스프링 기능을 활용할 것이다.
스프링 DI컨테이너가 관리할 수 있도록 AppConfig 파일에 어노테이션을 추가해주자.
∨ 설정파일이라는 뜻에서 AppConfig에다가 @Configuration을 붙인다.
∨ 여기서 @Bean 메서드가 호출되어 반환된 객체는 스프링 컨테이너에 등록된다. 그러한 객체를 스프링 빈이라고 한다.
스프링 빈 이름 : 메서드 이름
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class 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 RateDiscountPolicy();
}
}
① MemberService가 스프링을 이용하도록 변경하자.
스프링 적용 X : AppConfig를 직접 가져왔음
스프링 적용 O : ApplicationContext가 관리한다.
∨ ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
: annotation을 기반으로 한 config라서 이름이 저렇다.
: ApplicationContext가 스프링 컨테이너다. (참고: 인터페이스임)
∨ applicationContext.getBean("memberService", MemberService. class);
: getBean : 빈 이름으로 객체(스프링 빈)을 가져온다.
: 매개변수 : 스프링빈 이름, 반환타입
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MemberApp {
public static void main(String[] args) {
// AppConfig appConfig = new AppConfig();
// MemberService memberService = appConfig.memberService();
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
Member member = new Member(1L, "memberA", Grade.VIP);
memberService.join(member);
Member findMember = memberService.findMember(1L);
System.out.println("new member : " + member.getName());
System.out.println("findMember : " + findMember.getName());
}
}
실행해보면 :
오... 막 singleton 스프링 빈이 생성된다.
① OrderService도 같은 과정으로 변경하자.
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class OrderApp {
public static void main(String[] args) {
// AppConfig appConfig = new AppConfig();
// MemberService memberService = appConfig.memberService();
// OrderService orderService = appConfig.orderService();
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
Long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 10000);
System.out.println("order = " + order);
System.out.println("order.calculatePrice = " + order.calculatePrice());
}
}
이전에 AppConfig를 직접 이용하던 것을
스프링 컨테이너를 통해서 스프링 빈을 찾아쓰는 방식으로 변경한 것이다!
스프링 적용 X : AppConfig를 직접 가져왔음
스프링 적용 O : ApplicationContext가 관리한다.
(참고)
스프링 컨테이너는 '스프링 빈 생성'과 '의존관계 주입'의 과정이 분리되어있다.
우리가 AppConfig에서 작성한 아래의 자바 생성자 코드상에서는 두 과정이 뒤섞여있기는 하지만
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class 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 RateDiscountPolicy();
}
}
스프링 사이클상 기본적으로 두 단계는 분리되어있다는 것은 알아두자.
cf. 단계의 분리 : bean생성 -> @Autowired(의존관계주입)
cf. 수정자(setter)를 사용할 경우 두번째단계에서 의존관계 주입이 일어난다.
cf. 단, 생성자 주입인 경우는 자바코드 특성상 bean생성할 때 의존관계주입이 같이 일어난다.
? 스프링 컨테이너로 관리하면 좋은점??
엄청 많다고 하는데 이제부터 공부하게된닷
다음 학습 : 스프링컨테이너의 핵심기능, 스프링 빈을 더 자세히 알아가는 학습
'web +a' 카테고리의 다른 글
스프링 빈 조회 (getBean) - 상속관계인 경우 (0) | 2022.07.06 |
---|---|
(컨테이너에 등록된) 스프링 빈 조회해보기 (0) | 2022.07.06 |
IoC/DI컨테이너 (0) | 2022.07.05 |
AppConfig 리팩터링 (+ 역할 요약) (0) | 2022.07.05 |
도메인 설계 내용 (작성중) (0) | 2022.07.04 |