스프링 컨테이너로 등록하기
@Configuration
설정 클래스를 스프링 빈으로 등록하기 위해서는 @Configuraition 어노테이션을 붙여준다. 이번에도 AppConfig 클래스를 예시로 들겠다.
AppConfig 클래스(DI 컨테이너)
package hello.core;
@Configuration // @Configuration : 설정 정보
public class AppConfig {
.....
}
@Bean
사실 AppConfig는 다음과 같이 구현되어 있다.
AppConfig 클래스(DI 컨테이너) 내부 모습
package hello.core;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration // @Configuration : 설정 정보
public class AppConfig {
@Bean // @Bean : 스프링 컨테이너 등록
public MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy(){
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
@Bean
public MemberService memberService(){
//생성자 주입
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService(){
//생성자 주입
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
}
AppConfig를 보면 메소드에 @Bean 어노테이션이 존재한다.
@Bean은 해당 메소드를 수동으로 스프링 컨테이너에 빈으로 등록하는 어노테이션이다. 수동으로 빈을 등록할 때에는 메소드 이름으로 빈이 등록되므로 동일한 이름의 메소드를 등록하지 않도록 주의 해야한다.
스프링 컨테이너는 @Configuration 어노테이션이 붙은 클래스를 찾아서 자동으로 빈으로 등록해주고, 또한 해당 클래스를 파싱하여 @Bean이 붙은 메소드의 빈을 생성한다. @Bean을 사용하는 클래스에는 반드시 @Configuration 어노테이션을 활용하여 해당 클래스에서 Bean을 등록하고자 함을 명시해주어야 한다. 이는 싱글톤을 보장하기 위해서이다.
스프링 컨테이너 정리
기존의 OrderApp 클래스(클라이언트 클래스)
package hello.core;
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.order.Order;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
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();
Long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 20000);
System.out.println("order= " + order);
}
}
기존의 방식대로라면 위처럼 DI 컨테이너인 직접 AppConfig 클래스 객체를 생성해서 의존관계 주입을 담당하고 사용했다. 이는 실제로 OCP, DIP를 충족할 수 있는 훌륭한 방법이었다.
다만 이는 스프링 컨테이너를 사용하지 않은 순수 자바 코드만을 이용한 방식이고, 위에서 @Configuration, @Bean과 같이 스프링 빈으로 등록할 수 있는 방법을 배웠으니 스프링 컨테이너를 통해서 위의 코드를 구현할 수 있다.
스프링 컨테이너를 이용한 OrderApp 클래스(DI 컨테이너)
package hello.core;
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.order.Order;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class OrderApp {
public static void main(String[] args) {
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", 20000);
System.out.println("order= " + order);
}
}
16~22번 라인이 좀 바뀐 것을 볼 수 있다. 여기만 보자.
"ApplicationContext"를 스프링 컨테이너라고 한다. 또한 ApplicationContext는 인터페이스이다 기존에는 개발자가 AppConfig를 사용해서 직접 객체를 생성하고 DI를 했지만, 이젠 스프링 컨테이너를 통해서 사용을 한다.
스프링 컨테이너는 @Configuration이 붙은 AppConfig를 설정(구성)정보로 사용한다. 여기서 @Bean이라고 적힌 메소드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라고 한다.
요약
- @Configuration으로 DI 컨테이너를 스프링에 설정 정보로 등록
- @Bean 메소드에서 반환된 객체를 스프링 빈으로 등록
- 스프링 컨테이너에 등록된 객체를 스프링 빈이라고 함
이전에는 AppConfig를 사용해서 필요한 객체를 직접 조회했지만 이제는 스프링 컨테이너를 통해서 필요한 스프링 빈을 찾아야 한다. 스프링 빈은 applicationContext.getBean("조회 메소드명", 반환형)을 통해서 찾을 수 있다. (참고로 applicaitonContext는 위 소스코드에 나와있는 ApplicationContext 객체이다)
'Spring' 카테고리의 다른 글
Spring- 빈 관련 내용 정리 (0) | 2023.01.17 |
---|---|
Spring- 스프링 컨테이너로 등록하기(2) (0) | 2023.01.17 |
Spring- IoC, DI 컨테이너 (0) | 2023.01.17 |
Spring- Dependency Injection(의존 관계 주입) (0) | 2023.01.13 |
Spring- 객체 지향의 SOLID 원칙 (0) | 2023.01.12 |