[Spring] 3-6. 스프링으로 전환하기

송광호·2023년 12월 14일

[Spring]

목록 보기
16/41
post-thumbnail

Spring 시리즈는 혼자 공부하며 기록으로 남기고, 만약 잘못 학습 한 지식이 있다면 공유하며 피드백을 받고자 작성합니다.
스프링에 대해 깊게 공부해보고자 인프런의 김영한 강사님께서 강의를 진행하시는 (스프링 핵심 원리 - 기본편) 강의를 수강하며 정리하는 글입니다.
혹여나 글을 읽으시며 잘못 설명된 부분이 있다면 지적 부탁드리겠습니다.


스프링으로 전환하기

지금까진 순수한 100% 자바코드로만 DI를 적용했다.

AppConfig 스프링 기반으로 변경

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 OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

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

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    
}
  • AppConfig에 설정을 구성한다는 의미의 @Configuration을 붙여준다.
  • 각 메서드에는 @Bean을 붙여준다. 이 어노테이션이 붙으면 스프링 컨테이너에 스프링 빈으로 등록된다.

MemberApp에 스프링 컨테이너 적용

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());
    }
}
  • 스프링은 모든게 ApplicationContext라는걸로 시작을 한다. 이게 스프링 컨테이너라고 보면 된다.
  • ApplicationContext가 빈 객체들을 다 관리해준다.

OrderApp에 스프링 컨테이너 적용

public class OrderApp {
    public static void main(String[] args) {

//        AppConfig appConfig = new AppConfig();
//        OrderService orderService = appConfig.orderService();
//        MemberService memberService = appConfig.memberService();

        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
        OrderService orderService = applicationContext.getBean("orderService", OrderService.class);
        MemberService memberService = applicationContext.getBean("memberService", MemberService.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());

    }
}
  • 마찬가지로 스프링 컨테이너(ApplicationContext)에 등록된 빈 객체들을 applicationContext.getBean 메서드를 사용하여 가져온다.

스프링 컨테이너

  • ApplicationContext를 스프링 컨테이너라고 한다.
  • 기존 코드는 AppConfig를 사용하여 직접 객체를 생성하고 의존관계 주입(DI)를 했다. 이제부터는 스프링 컨테이너를 통해서 의존관계 주입을 한다.
  • 스프링 빈은 @Bean이 붙은 메서드의 명을 스프링 빈의 이름으로 사용한다.
    • (name = "value) 옵션으로 이름을 변경할 수는 있지만, 관례를 따르는것이 좋다. 그냥 쓰자.
  • 이제는 스프링 컨테이너를 통해서 필요한 스프링 빈(객체)을 찾아야 한다.
    • 스프링 빈은 applicationContext.getBean()메서드를 사용해서 찾을 수 있다.

왜 사용하는걸까..

  • 기존에 AppConfig에서 바로 꺼내는 코드가 더 간결한 것 같다.
  • 코드가 더 복잡해졌는데 스프링 컨테이너를 왜 사용할까?
    다음 강의부터 스프링 컨테이너에 대해 쭉 설명한다고 한다. 재밌겠다😀

스프링 부트 3.1 이상 로그 출력 안되는 문제

영한님 강의에서는 로그가 출력이 되는데 실행해보니깐 로그출력이 되지않는 문제가있다.
강의를 듣는시점이 부트가 2.대 버전이 없어서 3.2.0버전을 쓰고있는데 3.1이상버전은 로그출력이 되지않는다.
로그를 보고싶다면 아래 코드를 /src/main/resources/logback.xml에 추가하면 된다.
logback.xml

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp-
                %msg%n</pattern>
        </encoder>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

0개의 댓글