
객체지향의 장점을 활용하기 위한 DIP, OCP 원칙을 지키기위해 AppConfig를 통해 직접 DI관리를 했다.
스프링 프레임워크는 스프링 컨테이너를 통해 DI를 관리한다.
Configuration, Bean 어노테이션을 통해 스프링 컨테이너에 객체를 등록한다.
@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 FixDiscountPolicy();
return new RateDiscountPolicy();
}
}
스프링 컨테이너에 등록할 때, 구성파일로 활용될 AppConfig를 스프링 컨테이너가 등록할 객체들을 인식할 수 있게 @Configuration 어노테이션을 달아준다.
스프링 컨테이너는 @Configuration이 붙어있는 클래스를 자동으로 빈으로 등록,
해당 클래스에서 @Bean이 있는 메소드를 찾아서 빈 생성
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("find Member = " + findMember.getName());
}
}
스프링 컨테이너를 활용하기 전에는 기존에는 개발자가 AppConfig를 사용해서 직접 객체를 생성하고 DI를 진행했다.
여기서 스프링 컨테이너는 @Configuration이 붙은 AppConfig를 설정 정보로 사용하고, @Bean이라고 붙은 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다.
이렇게 등록된 객체를 스프링 빈이라고 한다. 즉, DI가 된 객체들이다.
정리하면, AppConfig에서 직접 호출해서 조회하는 방식에서 스프링 컨테이너에서 applicationContext.getBean() 메서드를 사용하여 찾는 방식으로 바뀌었다.
메인에서 이렇게 등록된 객체를 불러올 때, ApplicationContext를 호출해서 Bean을 가져오는데,
ApplicationContext를 스프링 컨테이너라고 한다.
더 정확히는 스프링 컨테이너를 부를 때 BeanFactory, ApplicationContext 로 구분한다.
하지만, BeanFactory를 직접 사용하는 경우는 거의 없어 ApplicationContext를 스프링 컨테이너라고 한다.

new AnnotationConfigApplicationContext(AppConfig.class)
이를 통해 스프링 컨테이너가 생성된다.
스프링 컨테이너를 생성할 때는 구성 정보를 지정해주어야하는 데, AppConfig.class가 구성 정보이다.

스프링 컨테이너는 파라미터로 넘어온 설정 클래스 정보를 사용해서 스프링 빈을 등록한다.
참고
빈 이름은 메서드 이름을 사용한다.
@Bean(name="이름") 방식으로 직접 부여도 가능하다.
%% 주의: 빈 이름은 항상 다른 이름은 부여! 같은 이름을 부여하게 될 경우 충돌난다.

스프링 컨테이너에는 빈 들이 등록이 되어있다.

스프링 컨테이너는 설정 정보를 참고해서 의존관계를 주입(DI)한다.
단순 자바 코드 호출처럼 보이지만, 싱글톤 컨테이너와 관련있다.
참고
정리된 글에서는 스프링은 빈을 생성하고, 의존관계를 주입하는 단계가 나누어져 있다.
그런데 자바 코드로 스프링 빈을 등록하면 생성자를 호출하면서 의존관계 주입도 한번에 처리된다.
이후 의존관계 자동 주입에서 자세히 다룰 예정이다...