/* ์ด ๊ธ์ ๊น์ํ๋์ ๊ฐ์๋ฅผ ๋ณด๊ณ ์ ๋ฆฌํ๋ ค๊ณ ์์ฑํ ๊ธ์ ๋๋ค.
๊ฐ์ธ์ ์ธ ๊ณต๋ถ๋ฅผ ์ํด ์ฌ๋ฆฌ๋ ๊ธ์ด๋ฏ๋ก ์ค๊ฐ ์ค๊ฐ ์ฝ๋๋ ์๋ต๋์์ต๋๋ค. */
์ฑ๊ธํค ์ปจํ ์ด๋
1. ์ฑ๊ธํค ์ปจํ ์ด๋
โ ์คํ๋ง ์ปจํ ์ด๋ ๋๋ถ์ ๊ณ ๊ฐ์ ์์ฒญ์ด ์ฌ ๋๋ง๋ค ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ด๋ฏธ ๋ง๋ค์ด์ง ๊ฐ์ฒด๋ฅผ ๊ณต์ ํด์ ํจ์จ์ ์ผ๋ก ์ฌ์ฌ์ฉ ํ ์ ์๋ค.
โ ๊ธฐ๋ณธ ๋น ๋ฑ๋ก ๋ฐฉ์์ ์ฑ๊ธํค์ด์ง๋ง, ์ฑ๊ธํค ๋ฐฉ์๋ง ์ง์ํ๋ ๊ฑด ์๋! ๋ค์ ๊ฐ์์์ ์ค๋ช ํด์ฃผ์ ๋ค๊ณ ํจ.
SingletonTest
@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);
Assertions.assertThat(memberService1).isSameAs(memberService2);
}
โ ์คํ๋ง ์ปจํ ์ด๋๋ ์ฑํดํค ํจํด์ ์ ์ฉํ์ง ์์๋, ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ์ฑ๊ธํค์ผ๋ก ๊ด๋ฆฌํ๋ค.
โ ์คํ๋ง ์ปจํ ์ด๋๋ ์ฑ๊ธํค ์ปจํ ์ด๋ ์ญํ ์ ํ๋ฉฐ, ์ด๋ ๊ฒ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ฑ๊ธํค ๋ ์ง์คํธ๋ฆฌ๋ผ ํ๋ค.
โ ์คํ๋ง ์ปจํ ์ด๋์ ์ด๋ฐ ๊ธฐ๋ฅ ๋๋ถ์ ์ฑ๊ธํค ํจํด์ ๋ชจ๋ ๋จ์ ์ ํด๊ฒฐํ๋ฉด์ ๊ฐ์ฒด๋ฅผ ์ฑ๊ธํค์ผ๋ก ์ ์งํ ์ ์๋ค.
์ฑ๊ธํค ๋ฐฉ์์ ์ฃผ์์
1. ์ฑ๊ธํค ๋ฐฉ์์ ์ฃผ์์
โ ๊ฐ์ฒด ์ธ์คํด์ค๋ฅผ ํ๋๋ง ์์ฑํด์ ๊ณต์ ํ๋ ์ฑ๊ธํค ๋ฐฉ์์ ์ฌ๋ฌ ํด๋ผ์ด์ธํธ๊ฐ ํ๋์ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค ๊ฐ์ฒด๋ ์ํ๋ฅผ ์ ์ง(stateful)ํ๊ฒ ์ค๊ณํ๋ฉด ์๋๊ณ ๋ฌด์ํ(stateless)๋ก ์ค๊ณํด์ผ ํ๋ค.
โ ๋ฌด์ํ๋?
- ํน์ ํด๋ผ์ด์ธํธ์ ์์กด์ ์ธ ํ๋๊ฐ ์์ผ๋ฉด ์๋จ.
- ํน์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ ํ๋๊ฐ ์์ผ๋ฉด ์๋จ.
- ๊ฐ๊ธ์ ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํด์ผํจ.
- ํ๋ ๋์ ์ ์๋ฐ์์ ๊ณต์ ๋์ง ์๋ ์ง์ญ๋ณ์, ํ๋ผ๋ฏธํฐ, ThreadLocal ๋ฑ์ ์ฌ์ฉํด์ผ ํ๋ค.
โ ์คํ๋ง ๋น์ ํ๋์ ๊ณต์ ๊ฐ์ ์ค์ ํ๋ฉด ์ ๋ง ํฐ ์ฅ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
2. ์ํ๋ฅผ ์ ์งํ ๊ฒฝ์ฐ ๋ฐ์ํ๋ ๋ฌธ์ ์ ์์
StatefulService
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;
}
}
StatefulServiceTest
class StatefulServiceTest {
static class TestConfig {
@Bean
public StatefulService statefulService() {
return new StatefulService();
}
}
@Test
void statefulServiceSingleton() {
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(StatefulService.class);
// ThreadA : A ์ฌ์ฉ์๊ฐ 10000์ ์ฃผ๋ฌธ
statefulService1.order("userA", 10000);
// ThreadB : B ์ฌ์ฉ์๊ฐ 20000์ ์ฃผ๋ฌธ
statefulService2.order("userB", 20000);
// ThreadA : A ์ฌ์ฉ์๊ฐ ์ฃผ๋ฌธ ๊ธ์ก ์กฐํ
int price = statefulService1.getPrice();
System.out.println("price = " + price);
Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
}
โ StatefulSerive์ price ํ๋๋ ๊ณต์ ๋๋ ํ๋์ธ๋ฐ, ํน์ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ์ ๋ณ๊ฒฝํ๋ค.
โ ์ฌ์ฉ์A์ ์ฃผ๋ฌธ๊ธ์ก์ 10000์์ด ๋์ด์ผ ํ๋๋ฐ, 20000์์ด๋ผ๋ ๊ฒฐ๊ณผ๊ฐ ๋์๋ค.
โ ์์๋ ์ต๋ํ ๋จ์ํ ์ค๋ช ํ๊ฑด๋ฐ ์ค์ ์ค๋ฌด์์ ์ด๋ฐ ๊ฒฝ์ฐ๋ฅผ ์ข ์ข ๋ณธ๋ค๊ณ ํ๋ค.
โ ๊ณต์ ํ๋๋ ์กฐ์ฌํด์ผ ํ๋ฉฐ ํญ์ ์คํ๋ฆฐ ๋น์ ๋ฌด์ํ๋ก ์ค๊ณํด์ผ ํ๋ค!