스프링 프레임워크는 애플리케이션 개발을 쉽게하고, 유지보수를 용이하게 하기 위해 다양한 기능을 제공한다. 이 중에서 스프링 컨테이너, 스프링 빈, 싱글톤 패턴, 싱글톤 컨테이너에 대해서 간략하게 공부해보자.
스프링 컨테이너는 스프링 프레임워크의 핵심이다. 컨테이너는 객체의 생성, 조립, 관리, 그리고 해체를 담당한다. ApplicationContext
인터페이스를 통해 제공된다. 주요 역할은 다음과 같다.
스프링 빈은 스프링 컨테이너에 의해 관리되는 객체를 의미한다. 빈은 애플리케이션의 구성 요소로, 보통 @Compenent
, @Service
, @Repository
, @Controller
, @Bean
어노테이션을 통해 정의된다.
싱글톤 패턴은 클래스의 인스턴스가 오직 하나만 생성되도록 보장하는 디자인 패턴이다. 주로 전역 상태를 유지하거나 리소스를 절약하기 위해 사용된다.
스프링 컨테이너는 기본적으로 싱글톤 컨테이너이다. 이는 컨테이너가 각 빈의 인스턴스를 한 번만 생성하고, 동일한 인스턴스를 재사용함을 의미한다.
// Bean 메서드를 호출해서 반환된 객체를 스프링 컨테이너에 등록한다.
@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();
}
}
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
public MemberRepository getMemberRepository() {
return memberRepository;
}
}
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);
MemberRepository memberRepository1 = memberService.getMemberRepository();
MemberRepository memberRepository2 = orderService.getMemberRepository();
System.out.println("memberService -> memberRepository = " + memberRepository1);
System.out.println("orderService -> memberRepository = " + memberRepository2);
System.out.println("memberRepository = " + memberRepository);
assertThat(memberService.getMemberRepository()).isSameAs(memberRepository);
assertThat(orderService.getMemberRepository()).isSameAs(memberRepository);
}
}
동일한 인스턴스를 재사용하는 것을 볼 수 있었다.
참고 코드