diff --git a/spring-core/basic/src/main/java/com/example/basic/AppConfig.java b/spring-core/basic/src/main/java/com/example/basic/AppConfig.java index 549a162c..1f1d26af 100644 --- a/spring-core/basic/src/main/java/com/example/basic/AppConfig.java +++ b/spring-core/basic/src/main/java/com/example/basic/AppConfig.java @@ -17,16 +17,19 @@ public class AppConfig { @Bean public MemberService memberService() { + System.out.println("call AppConfig.memberService"); return new MemberServiceImpl(memberRepository()); } @Bean public MemberRepository memberRepository() { + System.out.println("call AppConfig.memberRepository"); return new MemoryMemberRepository(); } @Bean public OrderService orderService() { + System.out.println("call AppConfig.orderService"); return new OrderServiceImpl(memberRepository(), discountPolicy()); } diff --git a/spring-core/basic/src/main/java/com/example/basic/member/MemberServiceImpl.java b/spring-core/basic/src/main/java/com/example/basic/member/MemberServiceImpl.java index b8a993e8..a40e4510 100644 --- a/spring-core/basic/src/main/java/com/example/basic/member/MemberServiceImpl.java +++ b/spring-core/basic/src/main/java/com/example/basic/member/MemberServiceImpl.java @@ -17,4 +17,9 @@ public class MemberServiceImpl implements MemberService { public Member findMember(Long memberId) { return memberRepository.findById(memberId); } + + // 테스트 용 + public MemberRepository getMemberRepository() { + return memberRepository; + } } diff --git a/spring-core/basic/src/main/java/com/example/basic/order/OrderServiceImpl.java b/spring-core/basic/src/main/java/com/example/basic/order/OrderServiceImpl.java index 2758b437..4f379e00 100644 --- a/spring-core/basic/src/main/java/com/example/basic/order/OrderServiceImpl.java +++ b/spring-core/basic/src/main/java/com/example/basic/order/OrderServiceImpl.java @@ -20,4 +20,9 @@ public class OrderServiceImpl implements OrderService { int discountPrice = discountPolicy.discount(member, itemPrice); return new Order(memberId, itemName, itemPrice, discountPrice); } + + // 테스트 용 + public MemberRepository getMemberRepository() { + return memberRepository; + } } diff --git a/spring-core/basic/src/test/java/com/example/basic/singleton/ConfigurationSingletonTest.java b/spring-core/basic/src/test/java/com/example/basic/singleton/ConfigurationSingletonTest.java new file mode 100644 index 00000000..042e8f41 --- /dev/null +++ b/spring-core/basic/src/test/java/com/example/basic/singleton/ConfigurationSingletonTest.java @@ -0,0 +1,39 @@ +package com.example.basic.singleton; + +import com.example.basic.AppConfig; +import com.example.basic.member.MemberRepository; +import com.example.basic.member.MemberServiceImpl; +import com.example.basic.order.OrderServiceImpl; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +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("memberRepository1 = " + memberRepository1); + System.out.println("memberRepository2 = " + memberRepository2); + System.out.println("memberRepository = " + memberRepository); + + Assertions.assertThat(memberService.getMemberRepository()).isSameAs(memberRepository); + Assertions.assertThat(orderService.getMemberRepository()).isSameAs(memberRepository); + } + + @Test + void configurationDeep() { + ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class); + AppConfig bean = ac.getBean(AppConfig.class); + + System.out.println("bean = " + bean.getClass()); + } +} diff --git a/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonService.java b/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonService.java new file mode 100644 index 00000000..cf104a49 --- /dev/null +++ b/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonService.java @@ -0,0 +1,16 @@ +package com.example.basic.singleton; + +public class SingletonService { + + private static final SingletonService instance = new SingletonService(); + + private SingletonService() {} + + public static SingletonService getInstance() { + return instance; + } + + public void logic() { + System.out.println("싱클톤 객체 호출"); + } +} diff --git a/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonTest.java b/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonTest.java new file mode 100644 index 00000000..828e0799 --- /dev/null +++ b/spring-core/basic/src/test/java/com/example/basic/singleton/SingletonTest.java @@ -0,0 +1,61 @@ +package com.example.basic.singleton; + +import com.example.basic.AppConfig; +import com.example.basic.member.MemberService; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import static org.assertj.core.api.Assertions.*; + +public class SingletonTest { + + @Test + @DisplayName("스프링 없는 DI 컨테이너") + void pureContainer() { + AppConfig appConfig = new AppConfig(); + + // 호출 할 때마다 객체를 생성 + MemberService memberService1 = appConfig.memberService(); + MemberService memberService2 = appConfig.memberService(); + + // 참조 값이 다른 것을 확인 + System.out.println("memberService1 = " + memberService1); + System.out.println("memberService2 = " + memberService2); + + // memberService1 != memberService2 + assertThat(memberService1).isNotSameAs(memberService2); + } + + @Test + @DisplayName("싱글톤 패턴 적용한 객체 사용") + void singletonServiceTest() { + SingletonService singletonService1 = SingletonService.getInstance(); + SingletonService singletonService2 = SingletonService.getInstance(); + + System.out.println("singletonService1 = " + singletonService1); + System.out.println("singletonService2 = " + singletonService2); + + // memberService1 != memberService2 + assertThat(singletonService1).isSameAs(singletonService2); + } + + @Test + @DisplayName("스프링 컨테이너와 싱글톤") + void springContainer() { + + AnnotationConfigApplicationContext 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); + + // memberService1 != memberService2 + assertThat(memberService1).isSameAs(memberService2); + } +} diff --git a/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulService.java b/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulService.java new file mode 100644 index 00000000..ff920491 --- /dev/null +++ b/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulService.java @@ -0,0 +1,15 @@ +package com.example.basic.singleton; + +public class StatefulService { + + private int price; // 상태를 유지하는 필드 + + public void order(String name, int price) { + System.out.println("name = " + name + " price = " + price); + this.price = price; + } + + public int getPrice() { + return price; + } +} diff --git a/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulServiceTest.java b/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulServiceTest.java new file mode 100644 index 00000000..6aee753b --- /dev/null +++ b/spring-core/basic/src/test/java/com/example/basic/singleton/StatefulServiceTest.java @@ -0,0 +1,36 @@ +package com.example.basic.singleton; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; + +class StatefulServiceTest { + + @Test + void statefulServiceSingleton() { + ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class); + StatefulService statefulService1 = ac.getBean(StatefulService.class); + StatefulService statefulService2 = ac.getBean(StatefulService.class); + + // A 사용자 10000원 주문 + statefulService1.order("userA", 10000); + // B 사용자 20000원 주문 + statefulService2.order("userB", 20000); + + // 사용자 A 주문 금액 조회 + int price = statefulService1.getPrice(); + System.out.println("price = " + price); + + Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000); + } + + static class TestConfig { + + @Bean + public StatefulService statefulService() { + return new StatefulService(); + } + } +}