- 애플리케이션은 보통 다수의 클라이언트들이 요청을 보냄, 매 요청마다 서버에 객체를 생성해서 전달하는 것은 메모리 낭비가 심함
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(new MemoryMemberRepository(), new RateDiscountPolicy());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy(){
return new RateDiscountPolicy();
//return new FixDiscountPolicy()
}
}
public class MemberApp {
public static void main(String[] args) {
AppConfig appConfig = new AppConfig();
MemberService memberService = appConfig.memberService();
Member member = new Member(1, "memberA", Grade.VIP);
memberService.join(member);
Member findMember = memberService.findMember(1L);
System.out.println("findMember.getName() = " + findMember.getName());
System.out.println("findMember.getName() = " + findMember.getGrade());
}
}
- 위와 같이 스프링을 사용하지 않은 AppConfig는 클라이언트에서 매번 new를 통해 새로운 객체를 생성하게 됨
싱글톤 패턴
- 최초에 static영역에 객체를 1개만 생성
- 외부에서는 getInstance() 메서드를 통해서만 객체를 받아갈 수 있도록 만듦
- 외부에서 생성자 호출을 못하도록 private생성자를 만들어 둠
public Class SingleTonService() {
private static final SingleTonService instance = new SingleTonService();
public static SingleTonService getInstance() {
return instance;
}
private SingleTonService(){}
}
스프링 컨테이너는 스프링 빈을 싱글톤으로 관리함
- 스프링 컨테이너에서는 직접 코드로 싱글톤을 구현하지 않아도 알아서 Bean을 하나만 생성해서 싱글톤으로 관리함
- 스프링 컨테이너를 사용하면 웹 애플리케이션에서 직접 싱글톤 구현 없이 간편하게 객체들을 싱글톤으로 관리할 수 있음
public class SingleTonTest {
@Test
void SingleTonTest() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService1 = ac.getBean("memberService", MemberService.class);
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
Assertions.assertThat(memberService1).isSameAs(memberService2);
}
}
memberService1 = com.example.member.MemberServiceImpl@5aac4250
memberService2 = com.example.member.MemberServiceImpl@5aac4250
CGLIB
- @Configuration을 사용하면 CGLIB를 사용함
- 스프링 컨테이너가 싱글톤 보장을 위해서 각 클래스를 싱글톤 패턴으로 코드를 생성하지 않고, 바이트코드를 조작하는 CGLIB 라이브러리를 사용
- 스프링 컨테이너는 AppConfig를 그냥 사용하지 않고, CGLIB를 활용하여 설정 클래스 AppConfig를 상속받는 임의의 클래스인 AppConfig$$EnhancerBySpringCGLIB$$6de7d4d1를 만들어서 스프링 Bean으로 등록
- AppConfig$$EnhancerBySpringCGLIB$$6de7d4d1 에는 스프링 Bean등록 작업을 할 때, 이미 스프링 컨테이너에 있으면, 존재하던 Bean을 반환, 없으면 생성해서 등록하는 코드가 생성되었을 것임..
public class MemberTest {
@Test
void MemberTest() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig appConfig = ac.getBean(AppConfig.class);
System.out.println("appConfig.getClass() = " + appConfig.getClass());
}
}
appConfig.getClass() = class com.example.demo.AppConfig$$EnhancerBySpringCGLIB$$6de7d4d1
'WEB > spring' 카테고리의 다른 글
[Spring] 의존관계 주입 방법(생성자/수정자/필드/메서드 주입) (0) | 2021.04.17 |
---|---|
[Spring] 컴포넌트 스캔, @ComponentScan, @AutoWired (0) | 2021.04.16 |
[Spring] 스프링 컨테이너, BeanFactory , ApplicationContext, BeanDefinition (0) | 2021.04.15 |
[Spring] 제어의 역전(IoC), 의존관계 주입(DI), 컨테이너 (0) | 2021.04.15 |
[Spring] 어플리케이션 Java설정 클래스 (0) | 2021.04.15 |