1. 스프링으로 전환
순수한 자바 코드로 DI를 적용했으니, 이제 스프링을 사용한다.
1) AppConfig 스프링 기반으로 변경
- src/main/java/hello/core/AppConfig.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 OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy() {
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
}
# @Configuration : 해당 클래스에 설정을 구성
# @Bean : 스프링 컨테이너에 스프링 빈으로 등록 (메서드 명으로 등록, name 속성을 사용해 이름을 바꿀 수 있지만 특별한 경우 아니면 기본값을 따름)
2) MemberApp에 스프링 컨테이너 적용
- src/main/java/hello/core/member/MemberApp.java
package hello.core.member;
import hello.core.AppConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MemberApp {
public static void main(String[] args) {
// AppConfig appConfig = new AppConfig();
// MemberService memberService = new MemberServiceImpl();
// 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());
}
}
3) OrderApp에 스프링 컨테이너 적용
- src/main/java/hello/core/order/OrderApp.java
package hello.core.order;
import hello.core.AppConfig;
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 OrderApp {
public static void main(String[] args) {
// MemberService memberService = new MemberServiceImpl();
// OrderService orderService = new OrderServiceImpl();
// 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);
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); // toString() 호출됨
System.out.println("order.calculatePrice = " + order.calculatePrice());
}
}
두 코드 실행시, 스프링 관련 로그가 몇 줄 나오면서 기존과 동일한 결과가 출력
4) 스프링 컨테이너
# ApplicationContext : 스프링 컨테이너
@Configuration 이 붙은 클래스를 설정(구성) 정보로 사용.
@Bean 이 붙은 메서드를 모두 호출하여 반환된 객체를 스프링 컨테이너에 스프링 빈으로 등록.
- AppConfig 를 사용해 직접 객체 생성 후 DI 했지만, 이제 스프링 컨테이너를 통해서 객체를 스프링 빈으로 등록.
- AppConfig 를 사용해 필요한 객체를 직접 조회했지만, 이제 스프링 컨테이너를 통해서 필요한 스프링 빈(객체) 찾는다.
스프링 빈은 applicationContext.getBean() 메서드를 통해 찾을 수 있다.
-> 개발자가 직접 자바 코드로 모든 것을 했지만, 이제 스프링 컨테이너를 이용하도록 변경되었다.
+ 스프링 부트 3.1 이상 - 로그 출력 안되는 문제 해결
- src/main/resources/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"> -->
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
스프링 부트 3.1 부터 기본 로그 레벨을 INFO 로 설정하기 때문에 로그를 확인할 수 없다. 따라서 기본 로그 레벨을 DEBUG 로 설정한다.
-> MemberApp, OrderApp 처럼 ApplicationContext 를 직접 생성해서 사용할 때만 적용된다.
CoreApplication 처럼 스프링 부트를 실행할 때는 이 파일을 제거하거나, <root level="DEBUG"> 에서 <root level="INFO"> 로 변경한다.
참고링크 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8?cid=325969
스프링 핵심 원리 - 기본편| 김영한 - 인프런 강의
현재 평점 5.0점 수강생 49,530명인 강의를 만나보세요. 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다. 스프링 기본 기능, 스프
www.inflearn.com
'강의 실습 > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
| 컨테이너에 등록된 모든 빈 조회 (0) | 2026.04.08 |
|---|---|
| 스프링 컨테이너 생성 (0) | 2026.04.07 |
| IoC, DI, 그리고 컨테이너 (0) | 2026.04.05 |
| 좋은 객체 지향 설계의 5가지 원칙의 적용 (0) | 2026.04.04 |
| 전체 흐름 정리 (0) | 2026.04.04 |
댓글