Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- JDBC
- jpa
- db
- springdatajpa
- 그리디
- 백준
- Android
- Thymeleaf
- Spring Boot
- Servlet
- SpringBoot
- 스프링 핵심 기능
- pointcut
- 스프링 핵심 원리
- java
- transaction
- spring
- kotlin
- 자바
- http
- Greedy
- Exception
- Proxy
- QueryDSL
- 스프링
- 인프런
- AOP
- JPQL
- 김영한
- 알고리즘
Archives
- Today
- Total
개발자되기 프로젝트
@Configuration, 싱글톤, 바이트코드 조작 본문
1. AppConfig에서 method호출할 때 마다 인스턴스가 생성?
- 기존에 작성한 AppConfig를 보면 memberRepository를 두 번 호출한다.
- 그러면 MemoryMemberRepository가 두 번 생성되나????
- 엥? 싱글톤인데??? 깨지나???
- 스프링 컨테이너는 싱글톤 보장해준다고 했는데..?
2. 그러면 두 클래스에 들어가는 memberRepository가 같은지 보자.
public class ConfigurationSingletonTest {
@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 = orderService.getMemberRepository();
MemberRepository memberRepository = ac.getBean("memberRepository", MemberRepository.class);
System.out.println("memberService --> memberRepository1 = " + memberRepository1);
System.out.println("orderService --> memberRepository2 = " + memberRepository2);
System.out.println("memberRepository = " + memberRepository);
}
}
- 두 빈에 들어간 memberRepository는 동일하고, memberRepository bean과 동일하다!!
memberService --> memberRepository1 = hello.core.member.MemoryMemberRepository@4b45dcb8
orderService --> memberRepository2 = hello.core.member.MemoryMemberRepository@4b45dcb8
memberRepository = hello.core.member.MemoryMemberRepository@4b45dcb8
3. 어떻게 한겨?
로직대로 실행되는게 아닌 것 같다.
memberRepository의 인스턴스는 모두 같은 인스턴스가 공유되어 사용된당
로직대로라면 두 번 호출되어 memberRepository의 인스턴스가 달라야 할 것 같은데..
각 메서드가 몇 번 호출되는지 보자.
@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 MemoryMemberRepository memberRepository() {
System.out.println("call AppConfig.memberRepository");
return new MemoryMemberRepository();
}
@Bean
public RateDiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
응? 예상과 다르다.
call AppConfig.memberService
call AppConfig.memberRepository
call AppConfig.orderService
4. @Configuration, 바이트코드 조작
- 스프링 컨테이너는 싱글톤 레지스트리 이다.
- 따라서 스프링 빈이 싱글톤이 되도록 보장해줘야 함.
- 자바 코드만 보면.. 메서드 호출될 때 마다 생성되어야 하는데..
- 이 문제를 해결하기 위해 스프링은 클래스 바이트코드를 주작한다.
- 핵심은! @Configuration 붙인 AppConfig이다.
- AppConfig도 bean으로 등록된다. appConfig bean의 클래스를 찍어보자.
@Test void configurationDeep(){ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); AppConfig bean = ac.getBean(AppConfig.class); System.out.println("bean = " + bean.getClass()); }
음? 뒤에 EnhancerBySpringCGLIB이 뭐지...
bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$58fbf5a5
- xxxCGLIB이 붙었다.
- 이것은 내가 만든 클래스가 아니라 스프링이 CGLIB이라는 바이트코드 조작 라이브러리를 사용하여
- AppConfig 클래스를 상속받은 다른 클래스를 만들고 그 다른 클래스를 빈으로 등록한 것!
- 즉, 스프링 컨테이너에 AppConfig$$EnhancerBySpringCGLIB이라 쓰고 AppConfig라 읽음.
- 즉 @Bean이 붙은 메서드 마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고
- 스프링 빈이 없으면 생성해서 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
5. @Configuration 안붙이면??
- CGLIB안돌아가서 싱글톤 보장 못 함!
- memberRepository처럼 의존관계 주입이 필요해서 메서드를 직접 호출할 때 싱글톤 보장 못함!
- 항상 붙이자 ㅋㅋㅋ
6. GitHub : 210727 Singleton, @Configuration
'인프런 > [인프런] Spring 핵심원리 이해' 카테고리의 다른 글
Component Scan의 탐색 위치와 스캔 대상 (0) | 2021.07.28 |
---|---|
Component 스캔, @Autowired (0) | 2021.07.28 |
싱글톤, 싱글톤 컨테이너, 스프링 컨테이너 (0) | 2021.07.27 |
스프링 빈 설정 메타정보 - BeanDefinition (0) | 2021.07.26 |
XML로 설정해보자아 (0) | 2021.07.26 |
Comments