728x90
package hello.core;

import hello.core.dicount.DiscountPolicy;
import hello.core.dicount.FixDiscountPolicy;
import hello.core.dicount.RateDiscountPolicy;
import hello.core.member.MemberRepository;
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
public class AppConfig {

    @Bean // spring container 에 등록
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(
                memberRepository(),
                discountPolicy()
        );
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }
}

 

 

@Configuration 데코레이터를 사용하여 Appconifg를 감싸줍니다.

 

그리고 각 Service에 @Bean 을 달아줍니다.

 

@Bean 데코레이터는 Spring container 에 관리 등록 을 하여 사용하게 편하게 해주는 데코레이터 입니다.

 

스프링 을 사용해 기존 코드를 리팩토링 해보겠습니다.

 

 

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();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);

        Member member = new Member(1L, "jongyun", Grade.VIP);
        memberService.join(member);

        Order item1 = orderService.createOrder(member.getId(), "item1", 7000);
        System.out.println("item1 = " + item1);
        System.out.println("discount price = " + item1.calculatePrice() );

    }
}

 

 

spring 은 모든게 ApplicationContext 라는 걸로 시작합니다.

 

이게 이제 spring container 라고 보시면 됩니다.

 

AppConfig.class << Configuration annotate 가 달린 class 를 파라미터로 넘기면

 

spring container 를 통해서 찾아오기

MemberService memberService = applicationContext.getBean("memberService", MemberService.class);

첫번째 파라미터로 메서드 이름을 적고 2번째 파라미터로 타입을 적어줍니다.

 

스프링 컨테이너

  • ApplicationContext 를 스프링 컨테이너라 한다.
  • 기존에는 개발자가 AppConfig 를 사용해서 직접 객체를 생성하고 DI를 했지만, 이제부터는 스프링 컨테이 너를 통해서 사용한다.
  • 스프링 컨테이너는 @Configuration 이 붙은 AppConfig 를 설정(구성) 정보로 사용한다. 여기서 @Bean 이라 적힌 메서드를 모두 호출해서 반환된 객체를 스프링 컨테이너에 등록한다. 이렇게 스프링 컨테이너에 등록된 객체를 스프링 빈이라 한다.
  • 스프링 빈은 @Bean 이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다. ( memberService , orderService )
  • 이전에는 개발자가 필요한 객체를 AppConfig 를 사용해서 직접 조회했지만, 이제부터는 스프링 컨테이너 를 통해서 필요한 스프링 빈(객체)를 찾아야 한다.
  • 스프링 빈은 applicationContext.getBean() 메서드 를 사용해서 찾을 수 있다.-
  • 기존에는 개발자가 직접 자바코드로 모든 것을 했다면 이제부터는 스프링 컨테이너에 객체를 스프링 빈으로 등록하고, 스프링 컨테이너에서 스프링 빈을 찾아서 사용하도록 변경되었다.

 

실제 동작 화면

 

처음 6개는 스프링이 자체적으 필요한 것들을 컨테이너 생성합니다.

 

그런뒤에 제가 작성한 appConfig부터 컨테이너에 생성하는 모습입니다.

728x90