코드 그라데이션
@Configuration과 싱글톤 본문
@Configuration과 싱글톤
AppConfig 코드를 보면
@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 RateDiscountPolicy();
}
}
검증 용도의 코드 추가 1 - MemberServiceImpl
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository; // 수정
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void join(Member member) {
memberRepository.save(member);
}
//테스트 용도 추가
public MemberRepository getMemberRepository() {
return memberRepository;
}
@Override
public Member findMember(Long memberId) {
return memberRepository.findById(memberId);
}
}
검증 용도의 코드 추가 2 - OrderServiceImpl
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
//테스트 용도 추가
public MemberRepository getMemberRepository() {
return memberRepository;
}
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
테스트 코드 - ConfigurationSingletonTest
package inflearn.spring_core.singleton;
import inflearn.spring_core.config.AppConfig;
import inflearn.spring_core.member.MemberRepository;
import inflearn.spring_core.member.MemberServiceImpl;
import inflearn.spring_core.order.OrderServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
public class ConfigurationSingletonTest {
@Test
void configurationTest() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class);
OrderServiceImpl orderService = ac.getBean("orderService", OrderServiceImpl.class);
MemberRepository memberRepository = ac.getBean("memberRepository", MemberRepository.class);
// 각각의 서비스와 레포지토리가 같은 인스턴스를 참조하고 있는지 확인
System.out.println("memberService -> memberRepository = " + memberService.getMemberRepository());
System.out.println("orderService -> memberRepository = " + orderService.getMemberRepository());
System.out.println("memberRepository = " + memberRepository);
//모두 같은 인스턴스를 참고하고 있다.
assertThat(memberService.getMemberRepository()).isSameAs(memberRepository);
assertThat(orderService.getMemberRepository()).isSameAs(memberRepository);
}
}
실행 결과
같은 인스턴스 참고중.
그런데,
AppConfig의 자바 코드를 보면 분명히 각각 2번 `new MemoryMemberRepository` 호출해서 다른 인스턴스가 생성되어야 하는데?
AppConfig에 호출 로그를 남긴다.
package inflearn.spring_core.config;
import inflearn.spring_core.discount.DiscountPolicy;
import inflearn.spring_core.discount.RateDiscountPolicy;
import inflearn.spring_core.member.MemberRepository;
import inflearn.spring_core.member.MemberService;
import inflearn.spring_core.member.MemberServiceImpl;
import inflearn.spring_core.member.MemoryMemberRepository;
import inflearn.spring_core.order.OrderService;
import inflearn.spring_core.order.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// 애플리케이션의 전체 동작 방식을 구성(config)하기 위해, 구현 객체를 생성하고, 연결하는 책임을 가지는 별도의 설정 클래스
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
// 여기
System.out.println("call AppConfig.memberService");
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
// 여기
System.out.println("call AppConfig.orderService");
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
// 여기
System.out.println("call AppConfig.memberRepository");
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
그런데 출력 결과
모두 한 번만 출력이 된다.
원래 에상 결과는 이렇게 되어야 할 것인데...
왜 그런지는 다음 포스트에서!
728x90
'Spring > 핵심 원리 구현' 카테고리의 다른 글
컴포넌트 스캔과 의존관계 자동 주입 시작하기 (0) | 2024.01.30 |
---|---|
@Configuration과 바이트코드 조작의 마법 (0) | 2024.01.29 |
싱글톤 방식의 주의점 (0) | 2024.01.27 |
싱글톤 컨테이너 (0) | 2024.01.27 |
싱글톤 패턴 (0) | 2024.01.26 |
Comments