22.12.01 12:07 작성
·
342
0
싱글톤과 Configuration이 무관하다는 글을 읽고 Test를 하던 중에 다음과 같이 짜봤습니다. (@Bean만 달려도 Singleton 보장이 된다) Test 클래스에 작성중입니다.
interface Example {
String getMsg();
}
static class TestMessage {
private String msg = "No Setter String";
public TestMessage(){
System.out.println("msg = " + msg);
System.out.println(this);
}
public String getMsg() {
return this.msg;
}
}
static class ChildExample implements Example {
private TestMessage testMessage;
@Autowired
public ChildExample(TestMessage testMessage) {
this.testMessage = testMessage;
}
@Override
public String getMsg() {
return this.testMessage.getMsg();
}
}
이렇게 세팅을 한 후 다음과 같이 Configuration 클래스를 만들어 봤습니다.
static class SingletonAndConfigurationAnnotationTest {
@Bean
public TestMessage testMessage() {
return new TestMessage();
}
@Bean
public Example example() {
return new ChildExample(new TestMessage());
}
}
그리고 다음과 같은 테스트 코드를 작성해봤습니다.
@Test
@DisplayName("안녕안녕")
void testA() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SingletonAndConfigurationAnnotationTest.class);
TestMessage bean1 = ac.getBean(TestMessage.class);
ChildExample bean2 = ac.getBean(ChildExample.class);
Assertions.assertThat(bean1).isSameAs(bean2.testMessage);
}
저는 TestMessage 가 우선 싱글톤으로 관리가 되므로, ChildExample 에는 그 싱글톤 TestMessage 객체가 의존성 주입이 될 것이라고 생각을 했습니다. 그리고 Configuration Annotation의 유무 차이를 실험해보려 했는데 실험 해보기도 전에 저 테스트 코드가 Fail을 하네요.. 아무리 생각해도 왜 두 객체가 다른지 모르겠습니다. 싱글톤으로 관리가 되어서 두 TestMessage는 같아야 하지 않나요? 로그에서도 다른 모습이 확인됩니다. (Configuration 무관하다 하셨지만 혹시 몰라 달아봤는데도 fail이 뜹니다)
11:34:02.853 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'testMessage'
msg = You can't edit this
com.example.basicprinciple.MyTest$TestMessage@5bf8fa12
11:34:02.858 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'example'
msg = You can't edit this
com.example.basicprinciple.MyTest$TestMessage@b2c5e07
왜 둘이 다른지 도움을 주실 수 있으실까요?
2.
또한 ComponentScan 에 관해서도 궁금한 점이 있습니다.
@ComponentScan(
basePackages = "com.example.basicprinciple"
)
public class AutoAppConfig {
}
강의에서 위와 같이 @ComponentScan을 설정해주셨습니다. 다만, 저런 방식이면 ComponentScan이 꼭 필요한가 싶어서 문의드립니다. 일반적으로 @controller, repository 등의 설정을 해놔도 다 Component로 이해를 하는데, 혹시 비즈니스 로직을 수행하는 함수들 외의 도움을 주는 Component들을 스캔하기 위함일까요?
3.
Configuration 과 Singleton이 무관하다고 해주신 것 같습니다. 혹시 강의 중 설명해주신 CGLIB을 따로 형성해서 싱글톤 관리가 되게 해주는건 @Bean 인걸까요? 만약 그렇다면, @Bean 함수의 묶음을 CGLIB 클래스로 만드는걸까요?
class XXCGLIB extends AppSprinfConfig{ // 내가 만든 Config의 자식 ...
@Override
@Bean
public Member membeRepository(){
if(ApplicationContext has MemoryMemberRepository){
return MemoryMemberRepository from Current Bean Container
}else{
build MemoryMemberRepository from My Class return MemoryMemberRepository
}
}
}
@Configuration 내부에 있는 클래스들이 다음과 같은 클래스로 바뀌어서 등록될 것으로 보인다고 강의안에서 설명해주셨는데, 저 묶음을 @Configuration으로 가져오는게 아니라면 @Bean들을 가지고 알아서 묶는건지 궁금합니다.
감사합니다.
답변 1
1
안녕하세요. kwj3591님, 공식 서포터즈 David입니다.
본 강의 '@Configuration과 바이트코드 조작의 마법'편을 참고해주세요. @Configuration이 붙은 설정 클래스에서 @Bean이 붙은 객체 생성 메서드의 동작 부분을 집중해서 봐주시면 됩니다. textMessage(), new TextMessage()의 차이점이 보이실거에요.
기본적으로 메인 메서드가 포함된 클래스에서 @ComponentSacn이 붙어 있습니다. 따라서, 모든 컴포넌트가 등록됩니다. 그런데 별도로 @ComponentScan을 쓰는 이유는 특정 범위, 조건을 제한하여 빈을 자동으로 등록하기 위함입니다.
@Configuration으로 인해 저렇게 만들어집니다. @Configuration과 싱글톤이 무관하다는 이유는 @Configuration이 없어도 @Bean만으로 싱글톤 빈으로 등록되기 때문입니다. 조금 더 엄밀히 말하면 @Bean이 붙은 메서드가 최초 호출되어 생성되는 객체를 싱글톤 빈으로 등록하는 게 @Configuration과 무관합니다. 그러나 @Configuration은 @Bean이 붙은 메서드를 재차 호출했을 때 싱글톤을 보장하는 것과 관련이 있습니다. 이 부분이 잘 이해되지 않으시다면 @Configuration 관련 강의를 반복해서 들어주세요.
아래 글과 답변도 참고해주세요.
감사합니다.
2022. 12. 06. 10:36
음.. 봐도 잘 모르겠어서 올린건데, 결론은 그냥 강의 반복해서 듣고 해결해라네요. 더 확인해보고 모르겠으면 질문하겠습니다.