@Configuration과 싱글톤

학습 페이지

@Configuration이란 애너테이션은 사실 싱글톤을 위해 존재하는 녀석이다.

전에 만들었던 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 MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public OrderService orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }
    @Bean
    public DiscountPolicy discountPolicy() {
        return new RateDiscountPolicy();
    }

}

  1. 컨테이너에 빈을 저장하기 위해 @Bean이 붙어있는 memberService()를 호출한다고 해보자. 이를 위해 memberRepository() ⇒ MemoryMemberRepository()가 한번 호출된다.
  2. 이번엔 @Bean이 붙어있는 orderService()를 호출한다고 해보자. 이때도 memberRepository() ⇒ MemoryMemberRepository()가 한번 호출된다.

싱글톤이라고 했는데, 이렇게되면 적어도 두 개 이상의 객체가 실행되는 것 아닐까? 이미 작성된 자바코드를 스프링이 어떻게 하는 것도 아니고…


@Configuration애너테이션

위의 문제를 테스트를 통해 알아보기 위해, memberServiceImpl내에 객체를 반환하는 테스트용 메서드를 하나 만들어보자. 내부에 주입받은 객체 참조값 확인 용이다.

package hello.core.member;

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); //DIP 적용
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId); //DIP 적용
    }

    //싱글톤 테스트 용
    public MemberRepository getMemberRepositort() {
        return memberRepository;
    }
}

마찬가지로 orderServiceImple에도 같은 코드를 작성해주자.

Untitled

게터로 가져온 두 객체가 같은 객체인지(싱글턴인지)테스트 해보자.

    @Test
    void configurationTest () {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

        MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class);

        OrderServiceImpl orderService = ac.getBean("orderService", OrderServiceImpl.class);

        MemberRepository memberRepository1 = memberService.getMemberRepository();
        MemberRepository memberRepository2 = memberService.getMemberRepository();

        assertThat(memberRepository1).isSameAs(memberRepository2);

    }