# 스프링으로 전환하기

스프링 컨테이너

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

설정정보 AppConfig에 @Configuration 애노테이션을 붙여주고, 각각의 메서드가 시작되기 전에는 @Bean 애노테이션을 붙여준다.

스프링은 모두 ApplicationContext로 시작한다. 이것이 스프링 컨테이너라고 보면 된다.

**memberService** : **Key**, **내부 반환 객체 : Value**

```java
package hello.core;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.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
    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();
    }
}
```

MemberApp에 스프링 컨테이너 적용\
(이름, 타입)을 알려주면 스프링 컨테이너에서 객체를 찾아서 리턴한다!

```java
package hello.core;
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MemberApp {
    public static void main(String[] args) {
        //스프링은 AppConfig의 설정 정보를 가지고 @Bean 붙은 것들을 컨테이너에 객체 생성해서 관리한다!
        //이제 컨테이너를 통해서 객체를 가져와야한다!(이름,타입)을 알려주면 스프링 컨테이너에서 찾아서 반환해준다!
        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());
    } }
```

OrderApp에 스프링 컨테이너 적용

```java
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);
        //System.out.println("order.calculatePrice() = " + order.calculatePrice());
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://heunnajo.gitbook.io/spring/2/undefined-5.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
