[Spring ๊ธฐ๋ณธ] 4. ์คํ๋ง ์ปจํ ์ด๋์ ์คํ๋ง ๋น๐ซ
์๋ ํ์ธ์!
์ค๋๋ถํฐ ๋ณธ๊ฒฉ์ ์ผ๋ก ์คํ๋ง์ ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ณผ๊น ํฉ๋๋ค.
๊ณ ๊ณ ์ฝ!!

1. ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ
๋จผ์ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์์ฑ๋๋ ๊ณผ์ ์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
//์คํ๋ง ์ปจํ
์ด๋ ์์ฑ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
์ ๋ฒ ์น์ ๋ง์ง๋ง ์ฏ์์ ๋์๋ ์ฝ๋์ ๋๋ค.
new๋ก ํด์ AnnotationConfigApplicationContext ์ด๋ฆ๋ ๊ธด ์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด์ AppConfig๋ฅผ ํ๋ผ๋ฏธํฐ(๋งค๊ฐ๋ณ์)๋ก ๋๊ฒผ์ต๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ๋ฐํ๊ฐ์ผ๋ก ApplicationContext๊ฐ ๋์ต๋๋ค.
์ด ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ํ๊ณ , ์ธํฐํ์ด์ค์ ๋๋ค.
๋คํ์ฑ์ด ์ ์ฉ๋์ด์๋ ๊ฒ์ ๋๋ค.
์ด ApplicationContext ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ ๊ฒ ์ค์ ํ๋๊ฐ AnnotationConfigApplicationContext ์ ๋๋ค.
=> AnnotationConfigApplicationContext(AppConfig.class) ์ด ํด๋์ค๋ ApplicationContext ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด
์คํ๋ง ์ปจํ ์ด๋๋ XML ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค ์ ์๊ณ , Annotation ๊ธฐ๋ฐ์ ์๋ฐ ์ค์ ํด๋์ค๋ก ๋ง๋ค ์๋ ์์ต๋๋ค.
(์์ฆ์ XML ๊ธฐ๋ฐ์ผ๋ก ๋ง๋๋ ๊ฒ์ ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.)
์ ๋ฒ ์น์ ์์ AppConfig๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด Annotation ๊ธฐ๋ฐ์ ์๋ฐ ์ค์ ํด๋์ค๋ก ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ๋ง๋ ๊ฒ์ ๋๋ค.
<์ฐธ๊ณ โ๏ธ>
๋ ์ ํํ๋ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ๋ถ๋ฅผ ๋ BeanFactory, ApplicationContext๋ก ๊ตฌ๋ถํด์ ์๊ธฐํฉ๋๋ค.
BeanFactory๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์์ผ๋ฏ๋ก, ์ผ๋ฐ์ ์ผ๋ก ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ํฉ๋๋ค.
์ด ๋ถ๋ถ์ ๋ค์์ ๋ค๋ฃฐ ์์ ์ ๋๋ค.
1-1. ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ ๊ณผ์
1-1(1). ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ
1. new AnnotationConfigApplicationContext(AppConfig.class)๋ผ๊ณ ํ๋ฉด์ AppConfig์ ์ ๋ณด๋ฅผ ์ค๋๋ค.
2. ๊ทธ๋ฌ๋ฉด ์คํ๋ง ์ปจํ ์ด๋๊ฐ ๋ฑ ๋ง๋ค์ด์ง๋๋ค.
๊ทธ๋ฐ๋ฐ, ์ด ์คํ๋ง ์ปจํ ์ด๋ ์์๋ ์คํ๋ง ๋น ์ ์ฅ์๋ผ๋ ๊ฒ์ด ์์ต๋๋ค.
๊ทธ๋์, key๋ ๋น ์ด๋ฆ์ด ๋๊ณ , ๊ฐ์ ๋น ๊ฐ์ฒด๊ฐ ๋๋ ๊ฒ์ ๋๋ค.
=> ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๋๋ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ง์ ํด์ค์ผ ํฉ๋๋ค.
์ฌ๊ธฐ์๋ AppConfig.class๋ฅผ ๊ตฌ์ฑ ์ ๋ณด๋ก ์ง์ ํ์ต๋๋ค.
1-1(2). ์คํ๋ง ๋น ๋ฑ๋ก๐ซ
์คํ๋ง ์ปจํ ์ด๋๊ฐ ๋ณธ์ธ์ ์์ฑํ๋ฉด์ ์คํ๋ง ๋น ์ ์ฅ์์ ์คํ๋ง ๋น์ ๋ฑ๋กํฉ๋๋ค.
์ด๋ป๊ฒ ํ๋๋ฉด...
1. AppConfig.class ์ค์ ์ ๋ณด๋ฅผ ๋๊ธด ๊ฒ์์ @Bean ๋ถ์ ๊ฒ์ ํ๋์ฉ ๋ด ๋๋ค.
2. ๊ทธ๋ฆฌ๊ณ @Bean ๋ถ์ ๊ฒ์ ๋ค ํธ์ถํฉ๋๋ค.
ํธ์ถํด๋ณด๋๊น memberService๋ผ๋ ๋ฉ์๋ ์ด๋ฆ์ด ์๋ค์? ์ด ๋ฉ์๋ ์ด๋ฆ์ key(๋น ์ด๋ฆ)๋ก ๋ฑ๋กํฉ๋๋ค.
์ด key์ ๋ํ ๊ฐ์ return ํด์ new๋ก ๋ฐํํ๋ ๊ฐ์ฒด๋ฅผ ๋น ๊ฐ์ฒด๋ก ๋ฑ๋ก์ ํด์ค๋๋ค.
3. ์ง๊ธ ๊ทธ๋ฆผ์ ๋์์๋ ๊ฒ์ ์ด 4๊ฐ๋๊น ์ด 4๊ฐ๋ฅผ ๋ค ๋ฑ๋กํด์ค๋๋ค.
๊ทธ๋ฌ๋ฉด newํ ์ธ์คํด์ค ๊ฐ์ฒด 4๊ฐ๊ฐ ๋ค ๋ฑ๋ก์ด ๋๊ณ , ์ด๊ฒ์ ์คํ๋ง ๋น์ด๋ผ๊ณ ํฉ๋๋ค.
<์ฐธ๊ณ โ๏ธ>
- ๋น ์ด๋ฆ์ ๋ฒ ์๋ ์ด๋ฆ์ ์ฌ์ฉํฉ๋๋ค.
- ๋น ์ด๋ฆ์ ์ง์ ๋ถ์ฌํ ์๋ ์์ต๋๋ค.
=> @Bean (name = "memberService2")
<์ฃผ์!!โ ๏ธ>
๋น ์ด๋ฆ์ ํญ์ ๋ค๋ฅธ ์ด๋ฆ์ ๋ถ์ฌํด์ผ ํฉ๋๋ค.
๊ฐ์ ์ด๋ฆ์ ๋ถ์ฌํ๋ฉด, ๋ค๋ฅธ ๋น์ด ๋ฌด์๋๊ฑฐ๋ ๊ธฐ์กด ๋น์ ๋ฎ์ด๋ฒ๋ฆฝ๋๋ค.
์ด๋ฌ๋ฉด ์ค์ ์ ๋ฐ๋ผ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
1-1(3). ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์ค๋น๐ซ
์คํ๋ง ๋น์ ์ด๋ก์ ํ์์ ๊ทธ๋ฆผ์ผ๋ก ํํํ๋๋ก ํ๊ฒ ์ต๋๋ค. (์ฝฉ์ด์ด์..?ใ ใ ใ ๐ซ)
์ด๋ ๊ฒ ์ค๋น๋ฅผ ํด๋๊ณ , ๋ค์ ๋จ๊ณ๋ก ๋์ด๊ฐ๋ณด๊ฒ ์ต๋๋ค.
1-1(4). ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์๋ฃ๐ซ
์์กด๊ด๊ณ๋ฅผ ๋ฃ์ด๋ณผ๊ฑด๋ฐ์.
memberService์ ์์กด๊ด๊ณ๋ก๋ memberRepository๋ฅผ ๋ฃ์ด์คฌ์ต๋๋ค. (๋นจ๊ฐ์ ํ์ดํ ์ฐธ๊ณ )
์ด๋ ๊ฒ ์์กด๊ด๊ณ๊ฐ ๋๋ฉด new๋ก MemoryMemberRepository๊ฐ ๋ฆฌํด์ด ๋ฉ๋๋ค. (์ฝ๋ ์ฐธ๊ณ )
๊ทธ ๋ค์์ orderService๋ฅผ ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
orderService๋ memberRepository๋ ์์กดํ๊ณ (๋นจ๊ฐ์ ํ์ดํ), discountPolicy๋ ์์กดํฉ๋๋ค (ํ๋์ ํ์ดํ).
๊ทธ๋์, ์ด discountPolicy ์คํ๋ง ๋น์ ์ค์ ๋ก๋ new๋ก RateDiscountPolicy๊ฐ ๋ฆฌํด์ด ๋ฉ๋๋ค.
๋์ ์ธ ๊ฐ์ฒด ์ธ์คํด์ค ์์กด๊ด๊ณ๋ฅผ ์ค์ ๋ก ์คํ๋ง์ด ๋ค ์ฐ๊ฒฐํด์ค๋๋ค.
๊ทธ๋ผ ์ค์ ๋ก ์คํ๋ง ๋น์ด ๋ฑ ์ฐ๊ฒฐ์ด ๋ฉ๋๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ์ค์ ์ ๋ณด๋ฅผ ์ฐธ๊ณ ํ์ฌ ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ (DI)ํฉ๋๋ค.
๋จ์ํ ์๋ฐ ์ฝ๋๋ฅผ ํธ์ถํ๋ ๊ฒ ๊ฐ์ง๋ง ์ฐจ์ด๊ฐ ์์ต๋๋ค.
์ด ์ฐจ์ด๋ ๋ค์ ์ฑ๊ธํค ์ปจํ ์ด๋์์ ๋ณผ ์์ ์ ๋๋ค.
<์ฐธ๊ณ โ๏ธ>
์คํ๋ง ๋น์ ์์ฑํ๊ณ ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ ํ๋ ๋จ๊ณ๊ฐ ๋๋์ด์ ธ ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ์๋ฐ ์ฝ๋๋ก ์คํ๋ง ๋น์ ๋ฑ๋กํ๋ฉด ์์ฑ์๋ฅผ ํธ์ถํ๋ฉด์ ์์กด๊ด๊ณ ์ฃผ์ ๋ ํ ๋ฒ์ ์ฒ๋ฆฌ๊ฐ ๋ฉ๋๋ค.
์ฌ๊ธฐ์๋ ์ดํด๋ฅผ ๋๊ธฐ ์ํด ๊ฐ๋ ์ ์ผ๋ก ๋๋์ด์ ธ ์๊ณ , ์์ธํ ๋ด์ฉ์ ์์กด๊ด๊ณ ์๋ ์ฃผ์ ์์ ๋ค์ ๋์ฌ ์์ ์ ๋๋ค.
<์ ๋ฆฌโ๏ธ>
์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ๊ณ , ์ค์ (๊ตฌ์ฑ) ์ ๋ณด๋ฅผ ์ฐธ๊ณ ํด์ ์คํ๋ง ๋น๋ ๋ฑ๋กํ๊ณ , ์์กด๊ด๊ณ๋ ์ค์ ํ์ต๋๋ค.
์ด์ ์คํ๋ง ์ปจํ ์ด๋์์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.

2. ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์กฐํ
์คํ๋ง ์ปจํ ์ด๋์ ์ค์ ์คํ๋ง ๋น๋ค์ด ์ ๋ฑ๋ก๋์๋์ง ํ์ธํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๊ฑด ํ ์คํธ ์ฝ๋๋ก ํ ๋ฒ ์ง๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฐ์ test์์ hello.core์ beanfind๋ผ๋ ํจํค์ง๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์ด beanfind๋ผ๋ ํจํค์ง ์์ ApplicationContextInfoTest๋ผ๋ ์๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
๋ง๋ค๋ฉด ์ด๋ฐ ํ์ผ ๊ตฌ์กฐ๊ฐ ๋์ต๋๋ค.
ํ ์คํธ ์ฝ๋๋ฅผ ํ ๋ฒ ์ง๋ณด๊ฒ ์ต๋๋ค.
public class ApplicationContextInfoTest {
//๋๋ฌด ๊ธธ์ด์ ac๋ก ์ค์์ต๋๋ค.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋ชจ๋ ๋น ์ถ๋ ฅํ๊ธฐ")
void findAllBean() {
//ac.getBeanDefinitionNames(); ๊น์ง ์น๊ณ Ctrl + Alt + V ํ๋ฉด ์์ ํ์
ํ๊ณ ๋์ต๋๋ค.
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
//๋ฆฌ์คํธ๋ ๋ฐฐ์ด์ด ์์ผ๋ฉด iteration์ด๋ผ๊ณ ํด์ iter ์น๊ณ Tab ๋๋ฅด๋ฉด ๋ฐ์ for๋ฌธ์ด ๋์ต๋๋ค.
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object = " + bean);
}
}
}
์ฒซ ๋ฌธ์ฅ๋ถํฐ ์ฐจ๊ทผ์ฐจ๊ทผ ๋ด๋ณด๊ฒ ์ต๋๋ค.
ํจ์๋ช ์ ApplicationContextInfoTest๋ก ์ง์์ต๋๋ค.
public ์จ ์๋๋ฐ, JUnit5์์๋ถํฐ๋ ์์ public ์ ๋ถํ๋ ๋ฉ๋๋ค.
(์๋ต ๊ฐ๋ฅํ๋ฐ ์ผ๋จ ์ด๊ฑฐ ์๊ธฐํ๋ ค๊ณ ์ ์ด๋์ ๊ฒ์ ๋๋ค.)
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);๋ฅผ ํตํด์ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ์ต๋๋ค. ์์์๋ ๋ดค๋ ๋ด์ฉ์ ๋๋ค.
๋ณ์๋ช ์ ๋๋ฌด ๊ธธ์ด์ ac๋ก ์ค์์ต๋๋ค.
"๋ชจ๋ ๋น ์ถ๋ ฅํ๊ธฐ"๋ก ํด์ findAllBean์ผ๋ก ํจ์ ์ด๋ฆ์ ์ง์ด๋ณด์์ต๋๋ค.
void ์์ public๋ ์์์ ์๊ธฐํ ์ด์ ๋ก ์๋ตํ ๊ฒ์ ๋๋ค.
String[] beanDefinitionNames = ac.getBeanDefinitionNames(); ์ด ์ฝ๋์์ ์ด ์์ ๋ถ์ String ํ์ .. ์ฌ์ค ์ ์ฐ์๋์ง ๋ชจ๋ฆ ๋๋ค.
ac.getBeanDefinitionNames()์น๊ณ Window ๊ธฐ์ค Ctrl + Alt + V ์น๋ฉด ์์์ฒ๋ผ ํ์ ์ด ๋์ต๋๋ค.
์ด๋ค ํ์ ์ด ๋ฆฌํด ๋๋์ง ์์๋ณผ ํ์๊ฐ ์๋ค๋ ์ฅ์ ์ด ์์ฃ .
์์ ac.getBeanDefinitionNames()๋ ์คํ๋ง์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์ด๋ฆ์ ์กฐํํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ac.getBean()์ ๋น ์ด๋ฆ์ผ๋ก ๋น ๊ฐ์ฒด(์ธ์คํด์ค)๋ฅผ ์กฐํํฉ๋๋ค.
์ํผ ์ ์์ Object๋ String์ด ์ค๋์ง๋ ์คํ๋ง์ ๋ง๋ ์ฌ๋์ด ์ด๋ ๊ฒ ์ค๊ณ๋ฅผ ํด ๋ฒ๋ฆฐ ๊ฒ์ด์ด์ ํ์คํ๊ฒ๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง...
getBeanDefinitionNames๋ ์ด๋ฆ๋ค์ด ์ค๊ณ , ์ด๋ฆ์ String์ด์ฃ . ์ฌ๋ฌ ๊ฐ์ String๋ค์ด๋ผ String ๋ฐฐ์ด์ ์ฌ์ฉํ ๊ฒ์ด ์๋๊น ์กฐ์ฌ์ค๋ ์์ธกํด๋ด ๋๋ค...
๊ทธ ๋ค์ for๋ฌธ์ ๋ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ฌ์ค ์ด for๋ฌธ... ์์ ๋ฆฌ์คํธ๋ ๋ฐฐ์ด์ด ์์ผ๋ฉด iteration์ด๋ผ๊ณ ํด์ iter ์น๊ณ , Tab ๋๋ฅด๋ฉด ์ด๋ ๊ฒ for๋ฌธ์ด ๋์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , Object bean = ac.getBean(beanDefinitionName);๋ ์์ String๋์ ๊ฐ์ด Ctrl + Alt + V ์น๋ฉด ํ์ ์ ์๋ ค์ค๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น์ด ์ด๋ ๊ฒ ์ซ๋ผ๋ฝ ์ถ๋ ฅ์ด ๋์์ต๋๋ค.
์์ 5์ค์ ๋ค์๊ฐ ์งค๋ฆฌ๊ธด ํ์ง๋ง, ์์ 5์ค์ ์คํ๋ง์ด ๋ด๋ถ์ ์ผ๋ก ์คํ๋ง ์์ฒด๋ฅผ ํ์ฅํ๊ธฐ ์ํด์ ์ฐ๋ ๊ธฐ๋ฐ ๋น๋ค์ ๋๋ค.
์ฐธ๊ณ ๋ก appConfig๋ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก์ด ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์๋ 4์ค์ด ์ง์ง ๋ฑ๋กํ ์ ๋ค์ ๋๋ค.
๊ทผ๋ฐ, ๋ด๋ถ์ ์ธ ๊ฒ๋ค์ด๋ ๋ด๊ฐ ์ง ์ฝ๋๋ค์ด๋ ์์ด๋ฉด ์ซ ๊ทธ๋ด ์ ์์์์..ใ ์๋ฌด๋๋ ๋ณธ์ธ์ด ์ง ์ฝ๋๋ง ๋ณด๊ณ ์ถ์ ์๋ ์์ต๋๋ค.
์ ๋ ๊ทธ๋ ๊ฑฐ๋ ์.
๊ทธ๋์ applicationbean์ด๋ผ๋ ๊ฒ์ ํ ๋ฒ ์ถ๋ ฅํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Test
@DisplayName("์ ํ๋ฆฌ์ผ์ด์
๋น ์ถ๋ ฅํ๊ธฐ")
void findApplicationBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object = " + bean);
}
}
}
์์ ์ฝ๋๋ ๋น์ทํ๋ฐ, ๋ฑ ํ ์ค ๋ค๋ฅธ ๋ถ๋ถ์ด ์์ต๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ๋น์ ์ถ๋ ฅํ๊ธฐ ์ํด if๋ฌธ์ ์ฌ์ฉํด์ ์ญํ ์ Application์ผ๋ก ์ก์์ต๋๋ค.
<Role๐>
ROLE_APPLICATION: ์ง์ ๋ฑ๋กํ ์ ํ๋ฆฌ์ผ์ด์ ๋น
ROLE_INFRASTRUCTURE: ์คํ๋ง์ด ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋น
ํ ์คํธ๋ฅผ ์คํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ ๊ฒ ์ ๊ฐ ์์ฑํ ์ฝ๋๋ง ๋์ค๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.

3. ์คํ๋ง ๋น ์กฐํ
3-1. ๊ธฐ๋ณธ
์คํ๋ง ์ปจํ ์ด๋์์ ์คํ๋ง ๋น์ ์ฐพ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์กฐํ ๋ฐฉ๋ฒ์ ac.getBean(๋น ์ด๋ฆ, ํ์ )์ ๋๋ค.
๋น ์ด๋ฆ์ ์๋ตํ๊ณ , ac.getBean(ํ์ )์ฒ๋ผ ํ์ ๋ง ์ค๋ ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ, ์กฐํ ๋์ ์คํ๋ง ๋น์ด ์์ ์๋ ์์ต๋๋ค. ์ด๋ด ๋๋ ์์ธ๊ฐ ๋ฐ์ํ๋๋ฐ์.
NoSuchBeanDefinitionException: No bean named 'xxxxx' available ๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
๊ทธ๋ผ ์ฝ๋ฉ์ ์ง์ ํ ๋ฒ ํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ , Test ํจํค์ง์์ hello.core ์์ ์๋ beanfind ํจํค์ง์ ApplicationContextBasicFindTest ํด๋์ค๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
์ฐ์ , ๋น ์ด๋ฆ์ผ๋ก ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.
class ApplicationContextBasicFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ")
void findBeanByName() {
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
๋งจ ์์ public์ ์๋ตํ์์ต๋๋ค.
getBean(๋น ์ด๋ฆ="memberService", ํ์ =MemberService.class)๋ฅผ ํตํด ์กฐํํ์ต๋๋ค.
Assertions๋ฅผ ํตํด ๊ฒ์ฆ์ ํ์์ผ๋ฉฐ, Static ๋ฉ์๋ ์ถ๊ฐ๋ฅผ ํตํด Assertions๋ฅผ ์๋ตํ์์ต๋๋ค.
isInstanceOf๋ ๋ฐ์ดํฐ๊ฐ ๊ฐ์์ง ๊ฒ์ฆํ ๋ ์ฌ์ฉํฉ๋๋ค.
Assertions ๋ถ๋ถ์์ isInstanceOf(MemberServiceImpl.class)์์ MemberServiceImpl ๋์ ์ ์ธํฐํ์ด์ค์ธ MemberService๊ฐ ์๋ ํ ์คํธ๋ ์ ์๋ํฉ๋๋ค.
ํ ์คํธ๋ฅผ ํด๋ณด๊ฒ ์ต๋๋ค.
์ฑ๊ณต์ ์ผ๋ก ํ ์คํธ๊ฐ ๋์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
์ด๋ฒ์ ์ด๋ฆ ์์ด ํ์ ์ผ๋ก๋ง ์กฐํํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Test
@DisplayName("์ด๋ฆ ์์ด ํ์
์ผ๋ก๋ง ์กฐํ")
void findBeanByType() {
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
์๊น getBean(ํ์ =MemberService.class) ์ฌ๊ธฐ์์ ์ด๋ฆ์ด ์๋ต๋์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
ํ์ ์ผ๋ก๋ง ์กฐํํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ด๋ฆ์ ์ ์ง ์์ ๊ฒ์ ๋๋ค.
์ฌ๊ธฐ์์๋ isInstanceOf๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๊ฐ ๊ฐ์์ง ๊ฒ์ฆ์ ํ์ต๋๋ค.
ํ ์คํธ๋ฅผ ํด๋ณด๊ฒ ์ต๋๋ค.
์ญ์ ํ ์คํธ๊ฐ ์ ์งํ๋ ๊ฒ์ ๋ณผ ์ ์์ต๋๋ค.
์ด๋ ๊ฒ ์ธํฐํ์ด์ค๋ก ์กฐํ๋ฅผ ํ๋ฉด ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๊ฐ ์กฐํ ๋์์ด ๋ฉ๋๋ค.
๊ทธ๋ฐ๋ฐ, ์ด๊ฒ์ ๊ตฌ์ฒด ํ์ ์ผ๋ก ์กฐํ๋ฅผ ํ ์๋ ์์ต๋๋ค.
@Test
@DisplayName("๊ตฌ์ฒด ํ์
์ผ๋ก ์กฐํ")
void findBeanByName2() {
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);์์ ํ์ ๋ถ๋ถ์ธ MemberServiceImpl ๋ถ๋ถ์ด ์์์๋ MemberService๋ก ์ ์์ง๋ง, ์ฌ๊ธฐ์์๋ ๊ตฌํ์ฒด์ธ MemberServiceImpl๋ก ์ ์๋ค๋ ์ฐจ์ด์ ์ด ์์ต๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์ ์คํ๋๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
์ด๊ฑธ ์ ์๊ธฐํ๋์ง์ ๊ดํด์ ์ค๋ช ํ๊ธฐ ์ํด AppConfig๋ก ์ด๋ํด๋ณด๊ฒ ์ต๋๋ค.
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
ํ์ ์ MemberService๋ก ํ๊ธฐ ๋๋ฌธ์ ๊ผญ MemberService๋ก ํด์ผํ๋ ๊ฒ์ด ์๋๋๋ค.
์๋ํ๋ฉด, ์คํ๋ง ๋น์ ๋ฑ๋ก๋ ์ธ์คํด์ค ํ์ ์ ๋ณด๊ณ ๊ฒฐ์ ํ๊ธฐ ๋๋ฌธ์ ๊ผญ ์ธํฐํ์ด์ค์ฌ์ผ ํ๋ ๊ฒ์ด ์๋๊ณ ๊ทธ ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด์ฌ๋ ์๊ด์ด ์์ต๋๋ค.
๋ชฐ๋ก , ๊ตฌ์ฒด์ ์ผ๋ก ์ ๋ ๊ฒ์ ์ข์ง ์์ต๋๋ค.
ํญ์ ์ญํ ๊ณผ ๊ตฌํ์ ๊ตฌ๋ถํด์ผํ๊ณ , ์ญํ ์ ์์กดํ๋๋ก ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค.
์์ ์ฝ๋๋ค์ ๊ตฌํ์ ์์กดํ๊ณ ์์ต๋๋ค.
ํญ์ ์ฝ๋๋ฅผ ๊ตฌํํ ๋๋ ์คํจํ๋ ์ฝ๋๋ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ")
void findBeanByNameX() {
//ac.getBean("XXXXX", MemberService.class);
MemberService XXXXX = ac.getBean("XXXXX", MemberService.class);
}
์ฐ์ ๊ฒ์ฆ๊ณผ์ ์์ด ํด๋ณด๊ฒ ์ต๋๋ค.
์ค์ ์ ํฌ๊ฐ ๊ตฌํํ์ง ์์ ์ด๋ฆ์ธ XXXXX๋ฅผ ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.
๊ณผ์ฐ ๊ฒฐ๊ณผ๋ ์ด๋ป๊ฒ ๋์ฌ๊น์?
์คํจํฉ๋๋ค.
NoSuchBeanDefinitionException์ด๋ผ๋ ์์ธ๊ฐ ํฐ์ง๋ฉด์ XXXXX๋ผ๋ ์ด๋ฆ์ ๋น์ด ์กด์ฌํ์ง ์๋๋ค๊ณ ํฉ๋๋ค. ๋น์ฐํ ์ฌ์ค์ด์ฃ . ์ ํฌ๋ ์ด๋ฐ๊ฑฐ ๊ตฌํํ ์ ์ด ์์ผ๋๊น์~~
์ด๋ฒ์๋ ๊ฒ์ฆ ์ฝ๋๋ฅผ ์ถ๊ฐํด์ ๊ฒ์ฆ์ ํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ")
void findBeanByNameX() {
//ac.getBean("XXXXX", MemberService.class);
//MemberService XXXXX = ac.getBean("XXXXX", MemberService.class);
Assertions.assertThrows(NoSuchBeanDefinitionException.class,
() -> ac.getBean("XXXXX", MemberService.class);
}
์์ Assertions๋ ํ์์์ Assertions๊ณผ ๋ฌ๋ฆฌ JUnit์ Assertions์ ๋๋ค.
assertThrows๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ JUnit๊ฑฐ๋ก ํด์ผํ๋๋ผ๊ตฌ์.
assertThrows๋ ํ์ดํ ํจ์๊ฐ ์คํ๋ ๋, ์ผ์ชฝ ์ธ์๋ก ๋ฃ์ ์๋ฌ Exception์ด ํฐ์ง๋์ง ๊ฒ์ฌํ๋ ๋ฉ์๋ ์ ๋๋ค.
์์์ฒ๋ผ ๋๊ฐ์ด static import๋ฅผ ํด์ Assertions๋ฅผ ์๋ตํด๋ ๋ฉ๋๋ค.
์๋ฌ๊ฐ ํฐ์ง๋ฉด ํ ์คํธ๊ฐ ์ฑ๊ณตํฉ๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์๋ฌ๊ฐ ํฐ์ ธ์ ํ ์คํธ๊ฐ ์ฑ๊ณตํ์ต๋๋ค.
๊ธฐ์ตํด์ผ ํ ๊ฒ์ ๊ตฌ์ฒดํ์ ์ผ๋ก ๊ตฌํํ๋ฉด ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ค๋๊ฑฐ...
์ ๋งํ๋ฉด ์ญํ (์ธํฐํ์ด์ค)๋ก ํ์ธ์~~

3-2. ๋์ผํ ํ์ ์ด ๋ ์ด์
ํ์ ์ผ๋ก ์กฐํ๋ฅผ ํ ๋, ๊ฐ์ ํ์ ์ ์คํ๋ง ๋น์ด 2๊ฐ ์ด์์ด๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.
์ด? ๋ญ ์ ํํด์ผํ์ง..??
์ด ๋๋ ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋ฉ๋๋ค.
ac.getBeansOfType()์ ์ฌ์ฉํ๋ฉด ํด๋น ํ์ ์ ๋ชจ๋ ๋น์ ์กฐํํ ์ ์์ต๋๋ค.
ํ ๋ฒ ์กฐํ๋ฅผ ํด๋ณด๊ฒ ์ต๋๋ค.
์ฐ์ , test ํจํค์ง์์ hello.core์ beanfind ํจํค์ง์์ ApplicationContextSameBeanFindTest๋ผ๋ ์๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ค๋๋ค.
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด ์ค๋ณต ์ค๋ฅ ๋ฐ์")
void findBeanByTypeDuplicate() {
MemberRepository bean = ac.getBean(MemberRepository.class);
}
//static: ์ด ํด๋์ค ์์์๋ง ์ฌ์ฉํ๋ ค๊ณ static ์ฌ์ฉ
@Configuration
static class SameBeanConfig {
//๋น ์ด๋ฆ์ด ๋ค๋ฅธ๋ฐ ๊ฐ์ฒด ์ธ์คํด์ค ํ์
์ด ๊ฐ์ ์๋ ์์ต๋๋ค.
@Bean
public MemberRepository memberRepository1() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
AppConfig๋ฅผ ๊ท์ฐฎ๊ฒ ๋ ์ ๋๊ธฐ ๋ญ์๊ธฐํ๋๊น ์ด ํด๋์ค ์์์ SameBeanConfig๋ฅผ ๋ง๋ค์์ต๋๋ค.
์ฐ์ ํธ์ถํ๋ ๋ฐฉ์์ ์์์ ํ๋ ๊ฑฐ๋ ๋น์ทํฉ๋๋ค.
ac.getBean(MemberRepository.class);๋ฅผ ํด์ MemberRepository.class์ ๋น์ ํธ์ถํฉ๋๋ค.
๊ทธ๋ฐ๋ฐ, ์์์ ์ฐจ์ด์ ์ ๋ฐ์ SameBeanConfig๋ฅผ ๋ง๋ค์ด์ ์ด AppConfig๋ฅผ ์ด์ฉํ๊ณ , ์ฌ๊ธฐ ํด๋์ค ์์ memberRepository1, memberRepository2 2๊ฐ์ ๋น(๋น ์ด๋ฆ)์ ๋ง๋ค์์ต๋๋ค.
SameBeanConfig ํด๋์ค๋ ์ด ํด๋์ค ์์์๋ง ์ฌ์ฉํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ static์ ์ฌ์ฉํ์ต๋๋ค.
์ฌ๊ธฐ ์์์ ํ์ ์ ์ค๋ณต๋ MemberRepository์ ๋๋ค.
<๊ณผ์ >
1. ์ด๋ ๊ฒ ๋๋ฉด ์คํ๋ง ์ปจํ ์ด๋๊ฐ ๋ฐ ๋, ์ด SameBeanConfig๋ง ๊ฐ์ง๊ณ ์คํ๋ฉ๋๋ค.
2. ์ฌ๊ธฐ์๋ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์คํ๋ง ๋น memberRepository1, memberRepository2 2๊ฐ๋ฅผ ๋ฑ๋กํฉ๋๋ค.
3. ์ด๊ฒ์ ๋๋ ค๋ณด๋ฉด memberRepository๊ฐ 2๊ฐ๊ฐ ํ์ด๋์ฌ ๊ฒ์ ๋๋ค.
2๊ฐ ๋ค ํ์ ์ด MemberRepository๋ก ์ค๋ณต๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
4. ๊ทธ๋ผ ์คํ๋ง ์ ์ฅ์์ ๋ญ ์ ํํด์ผํ์ง..? ํฉ๋๋ค. ๊ทธ๋ฌ๊ณ NoUniqueBeanDefinitionException์ด๋ผ๋ ์์ธ๊ฐ ํฐ์ง ๊ฒ์ ๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์์์ ์๊ธฐํ ๊ทธ๋๋ก๋ค์. ์์ธ๊ฐ ํฐ์ก์ต๋๋ค.
ํ ์คํธ ํด๋ณด๊ณ ์คํจ ๊ฒฐ๊ณผ ์ซ๋ผ๋ฝ ๋ด๋ณด๋ฉด ์ด๋์ ๋ฌธ์ ๊ฐ ์๊ฒผ๋์ง ์ ์ ์์ต๋๋ค.
์น์ ํ๊ฒ memberRepository1, memberRepository2 ์ค ๋ญ ์ ํํด์ผํ ์ง ๋ชจ๋ฅด๊ฒ ๋ค ๋์ถฉ ์ด๋ฐ ๋์์ค๋ก ์ค๋ฅ๊ฐ ๋จ๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
ํ ์คํธ์ ์์ฑ ๋จ๊ณ๋ ๊ฒ์ฆ ๋จ๊ณ์ด๊ธฐ ๋๋ฌธ์ Assertions๋ฅผ ๋ง์ ์ถ๊ฐํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด ์ค๋ณต ์ค๋ฅ ๋ฐ์")
void findBeanByTypeDuplicate() {
//MemberRepository bean = ac.getBean(MemberRepository.class);
assertThrows(NoUniqueBeanDefinitionException.class,
() -> ac.getBean(MemberRepository.class));
}
์์์ฒ๋ผ ์๋ฌ ๊ด๋ จ์ด๊ธฐ ๋๋ฌธ์ JUnit์ Assertions๋ฅผ ์ฌ์ฉํ๊ณ , ๊ฑฐ๊ธฐ์ assertThrow๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
static import ํ๋ ๋ฐฉ๋ฒ์ ์ ์๋ ์๊ธฐํ์๋๋ฐ, assertThrows๋ง ์๋ ์ํ์์ ๋นจ๊ฐ์์ผ๋ก ๋จ๋ฉด ๊ฑฐ๊ธฐ์ ์ static ๋ฉ์๋ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ๋๋ฅด๊ฑฐ๋ Assertions์์ Alt+Enter๋ฅผ ์น๋ฉด ๋ฉ๋๋ค.
์ค๋ณต ์์ธ์ด๊ธฐ ๋๋ฌธ์ ์์์ ์๊ธฐํ NoUniqueBeanDefinitionException์ ์ฌ์ฉํ๊ณ , ํ์ ์ MemberReporitory์ด๊ธฐ์ MemberRepository.class๋ฅผ ์ ์ด์คฌ์ต๋๋ค.
ํ ์คํธ๋ฅผ ๋ค์ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์์ธ๊ฐ ํฐ์ ธ์ผ ์ฑ๊ณตํ๋ ๋ก์ง์ ๋๋ค.
์ญ์๋ ํ ์คํธ ์ฑ๊ณตํ์ต๋๋ค.
๊ทธ๋ผ ๋น ์ด๋ฆ ์ง์ ์ ํตํด ์์ธ ์ํฉ์ ํด๊ฒฐํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ ํ ์คํธ ์ฝ๋๋ฅผ ์ง๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด ๋น ์ด๋ฆ ์ง์ ์ ํตํด ํด๊ฒฐ")
void findBeanByName() {
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
๋น ์ด๋ฆ์ memberRepository1์ผ๋ก ์ง์ ํด์ ํด๊ฒฐ์ ์๋ํ์ต๋๋ค.
isInstanceOf๋ ์์์๋ ์ค๋ช ํ๋ค์ํผ ๋ฐ์ดํฐ๊ฐ ๊ฐ์์ง ๊ฒ์ฆํ ๋ ์ฌ์ฉํฉ๋๋ค.
assertThat(memberRepository)๋ฅผ ์น๊ณ ์ Alt+Enter๋ฅผ ์น๊ณ static import๋ฅผ ํ ๋, ์ฌ์ง์ฒ๋ผ 1๋ฒ์งธ ๊ฒ์ ๊ณ ๋ฅด๋ฉด ๋ฉ๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์ด๋ฒ์๋ ํน์ ์์ ์ ๋ชจ๋ ์กฐํํด๋ณด๊ฒ ์ต๋๋ค.
@Test
@DisplayName("ํน์ ํ์
์ ๋ชจ๋ ์กฐํํ๊ธฐ")
void findAllBeanByType() {
//String=Key, MemberRepository=Value
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
System.out.println("beansOfType = " + beansOfType);
assertThat(beansOfType.size()).isEqualTo(2);
}
์คํ๋ง์์ getBeansOfType() ํจ์์ Returnํ์ Map์ผ๋ก ๊ตฌํํด๋จ๊ธฐ ๋๋ฌธ์ Map ํจ์๊ฐ ์ฌ์ฉ๋์์ต๋๋ค.
๋, for (String key : beansOfType.keySet()) ์ฌ๊ธฐ๋ beansOfType ๋ณ์๊ฐ Map<String, MemberRepository>๋ผ๋ ํ์ ์ด์๋๋ฐ, ์ฌ๊ธฐ์ keySet()์ ํ๋ฉด <String, MemberRepository>์์์ ์ ๋ฐ์ดํฐ์ธ String ๋ฐ์ดํฐ๋ค๋ง ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
๋ ์ฝ๊ฒ ์ค๋ช ํด๋ณด๊ฒ ์ต๋๋ค.
beansOfType์ด๋ผ๋ ๋ณ์๋ ์์ ์ฌ์ง๊ณผ ๊ฐ์ด 2๊ฐ์ ๊ฐ์ด ์์ต๋๋ค.
๊ฐ๊ฐ์ ํ๋ ๊ฐ์ด String, MemberRepository ํ์ ๋ฐ์ดํฐ 2๊ฐ๋ฅผ ๊ฐ๊ณ ์๋ ๊ฒ์ ๋๋ค.
.keySet์ ํ๋ฉด ์์ชฝ์ ์๋ key ๊ฐ๋ค๋ก๋ง ํด์ ๋ฐฐ์ด์ ๋ง๋ค์ด์ค๋๋ค.
๊ทธ๋ฌ๋ฉด for๋ฌธ์ ํตํด ๋น ์ด๋ฆ์ ํ๋ํ๋ ์ถ๋ ฅํด์ค ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , .size๋ ์ฌ์ง์ฒ๋ผ Map์ ๋ฐ์ดํฐ๊ฐ ๋ช ๊ฐ๊ฐ ์๋ ํ์ธํ๋ ๊ฒ์ ๋๋ค.
MemoryMemberRepository์ DbMemberRepository 2๊ฐ๊ฐ ๋์์ผ ํ๊ธฐ์,
2๊ฐ๊ฐ ๋ง๊ฒ ๋์ค๋์ง Assertions์ assertThat์ผ๋ก ํ์ธํด์ฃผ๋ ๊ฒ์ ๋๋ค,
Q. ๊ทธ๋ผ ์ฌ๊ธฐ์ ์ง๋ฌธ! ๋ฐฐ์ด๊ณผ Map ํจ์์ ์ฐจ์ด์ ์ ๋ญ๊น์?
๋ฐฐ์ด์ ์ฌ์ง์ฒ๋ผ ๋ฐ์ดํฐ ํ๋ ๋น ํ ๋ฐ์ดํฐ๊ฐ ์์ต๋๋ค.
๊ทผ๋ฐ, Map์ ํ ๋ฐ์ดํฐ ๋น key์ value๋ผ๋ 2๊ฐ์ ๊ฐ์ผ๋ก ์ด๋ฃจ์ด์ ธ ์์ต๋๋ค.
์ฌ์ค ๊ทผ๋ฐ ๋ฐฐ์ด๊ณผ Map์ ๋น์ทํฉ๋๋ค.
Map ํจ์๋ Key์ Value๋ฅผ ํ ์์ผ๋ก ์ ์ฅํ๋ ๊ฐ์ฒด๊ณ , ๋ฐฐ์ด์ ํ๋ํ๋์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฐ์ฒด์ ๋๋ค.
๋ ๋ค ์ ์ฅํ๋ ์ ๋ค์ด์์~~
๊ทธ๋ผ ๋ค์ ๋ณธ๋ก ์ผ๋ก ๋ค์ด๊ฐ์... ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
ํ ์คํธ๊ฐ ์ ์๋ํฉ๋๋ค.

3-3. ์์ ๊ด๊ณ
์ฌ๊ธฐ๊ฐ ์คํ๋ง ๋น ์กฐํ ์ค์ ์ ์ผ ์ค์ํ ๋ถ๋ถ์ ๋๋ค.
๋ถ๋ชจ ํ์ ์ผ๋ก ์กฐํํ๋ฉด, ์์ ํ์ ๋ ํจ๊ป ์กฐํ๋ฉ๋๋ค.
๊ทธ๋์, ๋ชจ๋ ์๋ฐ ๊ฐ์ฒด์ ์ต๊ณ ๋ถ๋ชจ์ธ Object ํ์ ์ผ๋ก ์กฐํํ๋ฉด ๋ชจ๋ ์คํ๋ง ๋น์ ์กฐํํ ์ ์์ต๋๋ค.
(๋์๋ ์ ๋ณด์ด์ง๋ง ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค extends Object๊ฐ ์์ต๋๋ค.)
Test ํจํค์ง์ hello.core ์์ ์๋ beanfind ํจํค์ง์ ApplicationContextExtendsFindTest ์๋ฐ ํด๋์ค๋ฅผ ์ถ๊ฐํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
@Configuration
static class TestConfig {
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy FixDiscountPolicy() {
return new FixDiscountPolicy();
}
}
์์์ฒ๋ผ AppConfig ๊ฑด๋ค๊ธฐ ์ซ ๊ท์ฐฎ์์ง๊ธฐ ๋๋ฌธ์ ์ด ํด๋์ค ์์ ๋ฐ๋ก ํ ์คํธ Config๋ฅผ ๋ง๋ญ๋๋ค.
๋ณด๋ฉด ํ์ ์ DiscountPolicy๋ก ๊ฐ์ต๋๋ค. ํ์ ์ด ์ค๋ณต๋์ฃ .
DiscountPolicy ํ์ ์๋ฆฌ์ ์ฌ์ค ๊ฐ๊ฐ RateDiscountPolicy์ FixDiscountPolicy๊ฐ ์๋ ๋ฉ๋๋ค.
๊ทผ๋ฐ, ์ DiscountPolicy๋ก ์ผ์๊น์?
๊ทธ ์ด์ ๋ ์ญํ ๊ณผ ๊ตฌํ์ ํญ์ ์ชผ๊ฐ์ผํ๊ธฐ ๋๋ฌธ์ ๋๋ค. ๊ตฌ์ฒดํ๊ฐ ์๋ ์ถ์ํ๋ก ํด์ผ ์์กด๊ด๊ณ ์ฃผ์ ์ ํ ๋๋ ํจ์ฌ ์ฝ๋๊ฐ ๋ณด๊ธฐ ์ข์์ง๊ธฐ ๋๋ฌธ์ ๋๋ค.
๋ชฐ๋ก , ๊ตฌ์ฒดํ ํ์ ์ ์จ๋ ๋ฌธ์ ๋ ์์ต๋๋ค.
ํ ์คํธ ์ฝ๋๋ฅผ ๋ง์ ์ง๋ณด๊ฒ ์ต๋๋ค.
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค.")
void findBeanByParentTypeDuplicate() {
//DiscountPolicy bean = ac.getBean(DiscountPolicy.class);
assertThrows(NoUniqueBeanDefinitionException.class,
() -> ac.getBean(DiscountPolicy.class));
}
@Configuration
static class TestConfig {
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy FixDiscountPolicy() {
return new FixDiscountPolicy();
}
}
"๋ถ๋ชจ ํ์ ์ผ๋ก ์กฐํ ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํฉ๋๋ค"์ ๊ดํ ํ ์คํธ ์ฝ๋์ ๋๋ค.
์์์ฒ๋ผ ์ค๋ณต ์์ธ์ด๊ธฐ์ NoUniqueBeanDefinitionException์ ์ฌ์ฉํ๊ณ , ๊ทธ๋ฌ๊ธฐ์ Assertions์์ assertThrows๋ฅผ ์ฌ์ฉํ์ต๋๋ค.
(๊ฒ์ฆ ๋จ๊ณ ์ง์ฐ๊ณ ์ฃผ์์ฒ๋ฆฌ ๋์ด์๋ ๋ถ๋ถ ํ์ฑํ ํ๋ฉด ์ค์ ๋ก NoUniqueBeanDefinitionException์ด๋ผ๋ ์ค๋ฅ๊ฐ ๋น๋๋ค.)
ํ ์คํธ๋ฅผ ์งํํด๋ณด๊ฒ ์ต๋๋ค.
NoUniqueBeanDefinitionException ์์ธ๊ฐ ํฐ์ ธ์ผ ํ ์คํธ๊ฐ ์ฑ๊ณตํ๋ ๋ก์ง์ธ๋ฐ, ์ญ์๋ ์ฑ๊ณตํ์ต๋๋ค.
์ด๊ฑธ ํด๊ฒฐํ๊ธฐ ์ํด ๋น ์ด๋ฆ์ ์ง์ ํด๋ณด๋ ํ ์คํธ ์ฝ๋๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋ฉ๋๋ค.")
void findBeanByParentTypeBeanName() {
DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
๋น ์ด๋ฆ์ ์ง์ ํ๊ธฐ ๋๋ฌธ์ ๋ฐ๋ก ๊ฒ์ฆ๋จ๊ณ๋ฅผ ํด๋ ์ค๋ฅ๊ฐ ๋์ง ์์ต๋๋ค. (์ฃผ์ ๋ฐ์ ์๋ฐ)
์ญ์ ํ ์คํธ๊ฐ ์ฑ๊ณต์ ์ผ๋ก ์๋๋๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
๋น ์ด๋ฆ ์ง์ ๋ง๊ณ ๋ ๋ถ๋ชจ ํ์ ์ผ๋ก ์กฐํ ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ ํด๊ฒฐ์ ์ ๋ ์์ต๋๋ค.
ํน์ ํ์ ํ์ ์ผ๋ก ์กฐํํ๋ ๊ฒ์ธ๋ฐ์. ๊ทผ๋ฐ, ์ด ๋ฐฉ๋ฒ์ ์ข์ง ์์ต๋๋ค. ์ ์ง๋ ๊ตฌํ๊ณผ ์ญํ ... ์๊ฐํ๋ฉด ๋๊ฒ ์ฃ ?
@Test
@DisplayName("ํน์ ํ์ ํ์
์ผ๋ก ์กฐํ")
void findBeanBySubType() {
RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
}
ํน์ ํ์ ํ์ ์ผ๋ก ์กฐํํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ๋จ์ํ๊ฒ ํ๋๋ง ์๊ฒ ์ฃ ?
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
ํ ์คํธ๊ฐ ์ฑ๊ณตํ์ต๋๋ค.
์ด์ฐจํผ RateDiscountPolicy๋ TestConfig์์ ํ๋๋ฐ์ ์๊ธฐ ๋๋ฌธ์ ์ค๋ฅ๊ฐ ๋จ์ง ์๊ณ ๊ฒฐ๊ณผ๊ฐ ํ๋๋ก ์ ๋์ต๋๋ค.
์ด๋ฒ์๋ ๋ถ๋ชจ ํ์ ์ผ๋ก ๋ชจ๋ ์กฐํํ๋ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ๋ชจ๋ ์กฐํ")
void findAllBeanByParentType() {
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
assertThat(beansOfType.size()).isEqualTo(2);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
}
ํน์ ํ์ (๋ถ๋ชจ ํ์ )์ ๋ชจ๋ ์กฐํํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ beansOfType์ ์ฌ์ฉํ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์คํ๋ง์์ getBeansOfType() ํจ์์ Returnํ์ Map์ผ๋ก ๊ตฌํํด๋จ๊ธฐ ๋๋ฌธ์ Map ํจ์๊ฐ ์ฌ์ฉ๋์์ต๋๋ค.
๋, for (String key : beansOfType.keySet()) ์ฌ๊ธฐ๋ beansOfType ๋ณ์๊ฐ Map<String, DiscountPolicy>๋ผ๋ ํ์ ์ด์๋๋ฐ, ์ฌ๊ธฐ์ keySet()์ ํ๋ฉด <String, DiscountPolicy>์์์ ์ ๋ฐ์ดํฐ์ธ String ๋ฐ์ดํฐ๋ค๋ง ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
๋ ์ฝ๊ฒ ์ค๋ช ํด๋ณด๊ฒ ์ต๋๋ค.
(์ฌ์ค 3-2์ ์๋ beansOfType์ Map ํจ์์ ๋ค๋ฅผ๊ฒ ์์ต๋๋ค.)
beansOfType์ด๋ผ๋ ๋ณ์๋ ์์ ์ฌ์ง๊ณผ ๊ฐ์ด 2๊ฐ์ ๊ฐ์ด ์์ต๋๋ค.
๊ฐ๊ฐ์ ํ๋ ๊ฐ์ด String, DiscountPolicy ํ์ ๋ฐ์ดํฐ 2๊ฐ๋ฅผ ๊ฐ๊ณ ์๋ ๊ฒ์ ๋๋ค.
.keySet์ ํ๋ฉด ์์ชฝ์ ์๋ key ๊ฐ๋ค๋ก๋ง ํด์ ๋ฐฐ์ด์ ๋ง๋ค์ด์ค๋๋ค.
๊ทธ๋ฌ๋ฉด for๋ฌธ์ ํตํด ๋น ์ด๋ฆ์ ํ๋ํ๋ ์ถ๋ ฅํด์ค ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , .size๋ ์ฌ์ง์ฒ๋ผ Map์ ๋ฐ์ดํฐ๊ฐ ๋ช ๊ฐ๊ฐ ์๋ ํ์ธํ๋ ๊ฒ์ ๋๋ค.
FixDiscountPolicy์ RateDiscountPolicy 2๊ฐ๊ฐ ๋์์ผ ํ๊ธฐ์,
2๊ฐ๊ฐ ๋ง๊ฒ ๋์ค๋์ง Assertions์ assertThat์ผ๋ก ํ์ธํด์ฃผ๋ ๊ฒ์ ๋๋ค,
๋ณธ๋ก ์ผ๋ก ๋ค์ด๊ฐ์..
์ฐธ๊ณ ๋ก ํ ์คํธ ์ฝ๋์์ ์ถ๋ ฅ๋ฌธ์ ์ค๋ฌด์์ ์ฌ์ฉ ์ ํฉ๋๋ค.
๊ณต๋ถ์ฉ์ด๋๊น ๋ณด๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด์ ์ฌ์ฉํ๋ ๊ฒ์ด์์.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์ถ๋ ฅ๋ฌธ ์ ์ ๋ฐ๋ก ๊ฒฐ๊ณผ๊ฐ ์์ฃผ ์ ๋์ต๋๋ค.
๋ง์ง๋ง์ผ๋ก, ์๊น์ฒ๋ผ ๋ถ๋ชจ ํ์ ์ผ๋ก ๋ชจ๋ ์กฐํํ ๊ฑด๋ฐ, Object ํ์ ์ผ๋ก ๊บผ๋ด๋ ๊ฒ์ ํด๋ณด๊ฒ ์ต๋๋ค.
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ๋ชจ๋ ์กฐํ - Object")
void findAllBeanByObjectType() {
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
}
์ต์์ ๊ฐ์ฒด์ธ Object์ผ๋ก ์กฐํํด๋ณด์์ต๋๋ค.
์์๋ ๋น์ทํ ๊ฒฝ์ฐ์ด๊ธฐ ๋๋ฌธ์, beansOfType์ ์ฌ์ฉํ๊ตฌ์. ๊ทธ๋ ๊ธฐ์ Map ํ์ ์ ์ฌ์ฉํ์ต๋๋ค.
๋ฐ๋ก ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์ด์ผ.... ์์ฒญ ๋ง์ด ์ถ๋ ฅ๋์์ต๋๋ค.
์ง๊ธ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ๋ญ๊ฐ ์คํ๋ง์ด ๋ด๋ถ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋น๋ค๊น์ง ๋ค ์ถ๋ ฅ๋์์ต๋๋ค.
์คํ๋ง ์์๋ ์ฌ๋ฌ ๋น๋ค์ด ๋ฑ๋ก๋์ด์๋๋ฐ ์๋ค๋ค๊น์ง ๋ค ์ถ๋ ฅ๋ ๊ฒ์ ๋๋ค.
์๋ํ๋ฉด, ์๋ฐ ๊ฐ์ฒด๋ ๋ชจ๋ ๊ฒ์ด Object ํ์ ์ด๊ธฐ ๋๋ฌธ์ ๋๋ค.

4. BeanFactory์ ApplicationContext
beanFactory์ ApplicationContext์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
4-1. BeanFactory
- ์คํ๋ง ์ปจํ ์ด๋์ ์ต์์ ์ธํฐํ์ด์ค์ ๋๋ค.
- ์คํ๋ง ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ์ญํ ์ ๋ด๋นํฉ๋๋ค.
- getBean()์ ์ ๊ณตํฉ๋๋ค.
- ์ง๊ธ๊น์ง ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๋๋ถ๋ถ์ ๊ธฐ๋ฅ์ BeanFactory๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ ๋๋ค.
4-2. ApplicationContext
- BeanFactory ๊ธฐ๋ฅ์ ๋ชจ๋ ์์๋ฐ์ ์ ๊ณตํฉ๋๋ค.
- ๋น์ ๊ด๋ฆฌํ๊ณ ๊ฒ์ํ๋ ๊ธฐ๋ฅ์ BeanFactory๊ฐ ์ ๊ณตํด์ฃผ๋๋ฐ, ๊ทธ๋ฌ๋ฉด ๋์ ์ฐจ์ด๊ฐ ๋ญ๊น์?
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋๋ ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ชฐ๋ก ์ด๊ณ ์ ๋ง์ ๋ถ๊ฐ ๊ธฐ๋ฅ์ด ํ์ํฉ๋๋ค.
<ApplicationContext๊ฐ ์ ๊ณตํ๋ ๋ถ๊ฐ ๊ธฐ๋ฅ>
- ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น ๊ธฐ์ต!! ์ธํฐํ์ด์ค๋ ๋ค์ํ๊ฒ ๋ถ๋ฆฌ๋์ด ์์ต๋๋ค.
- ๋ฉ์์ง ์์ค๋ฅผ ํ์ฉํ ๊ตญ์ ํ ๊ธฐ๋ฅ
- ex) ํ๊ตญ์์ ๋ค์ด์ค๋ฉด ํ๊ตญ์ด๋ก, ์์ด๊ถ์์ ๋ค์ด์ค๋ฉด ์์ด๋ก ์ถ๋ ฅํฉ๋๋ค. (๊ตญ์ ํ ๊ธฐ๋ฅ - ํ์ผ์ ์ฌ๋ฌ ๊ฐ๋ก ๋ถ๋ฆฌํด ๋์)
- ํ๊ฒฝ ๋ณ์
- ๋ก์ปฌ, ๊ฐ๋ฐ, ์ด์ ๋ฑ์ ๊ตฌ๋ถํด์ ์ฒ๋ฆฌํฉ๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์
์ด๋ฒคํธ
- ์ด๋ฒคํธ๋ฅผ ๋ฐํํ๊ณ ๊ตฌ๋ ํ๋ ๋ชจ๋ธ์ ํธ๋ฆฌํ๊ฒ ์ง์ํฉ๋๋ค.
- ํธ๋ฆฌํ ๋ฆฌ์์ค ์กฐํ
- ํ์ผ, ํด๋์ค ํจ์ค, ์ธ๋ถ ๋ฑ์์ ๋ฆฌ์์ค๋ฅผ ํธ๋ฆฌํ๊ฒ ์กฐํํฉ๋๋ค.
<์ ๋ฆฌโ๏ธ>
- ApplicationContext๋ BeanFactory์ ๊ธฐ๋ฅ์ ์์๋ฐ์ต๋๋ค.
- ApplicationContext๋ ๋น ๊ด๋ฆฌ ๊ธฐ๋ฅ + ํธ๋ฆฌํ ๋ถ๊ฐ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
- BeanFactory๋ฅผ ์ง์ ์ฌ์ฉํ ์ผ์ ๊ฑฐ์ ์์ต๋๋คโ๏ธ. ๋ถ๊ฐ ๊ธฐ๋ฅ์ด ํฌํจ๋ ApplicationContext๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- BeanFactory๋ ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ํฉ๋๋ค.

5. ๋ค์ํ ์ค์ ํ์ ์ง์ - ์๋ฐ ์ฝ๋, XML
๊น์ด๋ ์ดํด ์ ํด๋ ๋๊ณ , ๊ทธ๋ฅ ์ด๋ฐ๊ฒ ์๊ตฌ๋.. ์ ๋๋ก๋ง ์์๋๋ฉด ๋ฉ๋๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ๋ค์ํ ํ์์ ์ค์ ์ ๋ณด๋ฅผ ๋ฐ์๋๋ฆด ์ ์๊ฒ ์ ์ฐํ๊ฒ ์ค๊ณ๋์ด ์์ต๋๋ค.
์๋ฐ ์ฝ๋, XML, Groovy ๋ฑ๋ฑ ๋ง์ด์ฃ .
BeanFactory ์ธํฐํ์ด์ค ๋ฐ์ ApplicationContext ์ธํฐํ์ด์ค๊ฐ ์์ต๋๋ค.
๋, ApplicationContext ์ธํฐํ์ด์ค ๋ฐ์๋ AnnotationConfigApplicationContext, GenericXmlApplicationContext ๋ฑ์ด ์์ต๋๋ค.
AnnotationConfigApplicationContext๋ ์ ๋ ธํ ์ด์ ์ค์ ์ ๋ณด๋ฅผ ์ฌ์ฉํ๋ ApplicationContext๋ฅผ ๋ปํ๋ฉฐ, AppConfig.class๋ฅผ ์ฌ์ฉํฉ๋๋ค.
GenericXmlApplicationContext๋ ์๋ฐ ์ฝ๋๊ฐ ์๋ XML์ด๋ผ๋ ๋ฌธ์๋ฅผ ์ค์ ์ ๋ณด๋ก ์ฌ์ฉํ๋ ApplicationContext๋ฅผ ๋ปํ๋ฉฐ, appConfig.xml์ ์ฌ์ฉํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์์๋ก ๊ตฌํํด์ ๋ง๋ค ์๋ ์์ต๋๋ค. (XxxApplicationContext -> appConfig.xxx)
์์ฆ ์ฃผ๋ก ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ ์๋ฐ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ๋ AnnotationConfigApplicationContext์ด๊ณ , ๊ณผ๊ฑฐ์ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ XML์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ GenericXmlApplicationContext์ ๋๋ค.
XML์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ GenericXmlApplicationContext๊ฐ ์๋ ์ ๋ง์ด ์ฌ์ฉํ๋ ๊ฒ์ด๋ผ ํด๋ ์ด๊ฒ ์ด๋ป๊ฒ ๋์๊ฐ๋๊ตฌ๋.. ์ ๋๋ ์์์ผ ํฉ๋๋ค.
5-1. ์ ๋ ธํ ์ด์ ๊ธฐ๋ฐ ์๋ฐ ์ฝ๋ ์ค์ ์ฌ์ฉ
์ง๊ธ๊น์ง ํ๋ ๊ฒ์ ๋๋ค.
๊ทธ๋ฆฌ๊ณ , new๋ฅผ ํด์ AnnotationConfigApplicationContext๋ฅผ ๋ง๋ค๋ฉด์, AppConfig.class๋ผ๋ ์ค์ ์ ๋ณด๋ฅผ ๋ฃ์ด์คฌ์ต๋๋ค.
=> new AnnotationConfigApplicationContext(AppConfig.class)
์ฆ, AnnotationConfigApplicationContext ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด์ ์๋ฐ ์ฝ๋๋ก ๋ ์ค์ ์ ๋ณด๋ฅผ ๋๊ธฐ๋ฉด ๋๋ค๋ ๋ป์ ๋๋ค.
5-2. XML ์ค์ ์ฌ์ฉ
์ต๊ทผ์๋ ์คํ๋ง ๋ถํธ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ฉด์ XML ๊ธฐ๋ฐ์ ์ค์ ์ ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
๊ทธ๋ฌ๋, ์์ง ๋ง์ ๋ ๊ฑฐ์ ํ๋ก์ ํธ๋ค์ด XML๋ก ๋์ด ์๊ณ , ๋ XML์ ์ฌ์ฉํ๋ฉด ์ปดํ์ผ ์์ด ๋น ์ค์ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ์ฅ์ ๋ ์์ผ๋ฏ๋ก ํ ๋ฒ์ฏค ๋ฐฐ์๋ณด๋ ๊ฒ๋ ๊ด์ฐฎ์ ๊ฒ ๊ฐ์ต๋๋ค.
GenericXmlApplicationContext๋ฅผ ์ฌ์ฉํ๋ฉด์ xml ์ค์ ํ์ผ์ ๋๊ธฐ๋ฉด ๋ฉ๋๋ค.
ํ ๋ฒ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
test ํจํค์ง์ hello.core์ xml์ด๋ ํจํค์ง๋ฅผ ์ฐ์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์ด ํจํค์ง ์์ XmlAppContext ๋ผ๋ ์๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
public class XmlAppContext {
@Test
void xmlAppContext() {
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
์ฐ์ test ํด๋์ค๋ถํฐ ๋ง๋ค์์ต๋๋ค.
์์์ ํ๋ ๊ฑฐ๋ ๋น์ทํ๋ฐ GenericXmlApplicationContext๋ฅผ ์ฌ์ฉํ๋ค๋ ์ ์ด ๋ค๋ฅด๋ค์.
์ด๋๋ก ํ ์คํธ๋ฅผ ๋๋ฆฌ๋ฉด ์ค๋ฅ๊ฐ ๋ ์ AppConfig๋ฅผ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
test ํจํค์ง๊ฐ ์๋ src ํจํค์ง์ main ํจํค์ง์ resources ํจํค์ง ์์ (XML ๊ตฌ์ฑ ํ์ผ->Spring ๊ตฌ์ฑ ์ ํ)ํด์ appConfig.xml์ด๋ ์คํ๋ง ๊ตฌ์ฑ ํ์ผ์ ๋ง๋ญ๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
๋ง๋ค๋ฉด ์ด๋ ๊ฒ ์๋๋ฐ์. ์ฌ๊ธฐ ๋ฐ์๋ค๊ฐ ๋ง์ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
//์ฌ๊ธฐ์๋ถํฐ ์ถ๊ฐํ ๋ถ๋ถ
<bean id="memberService" class="hello.core.member.MemberServiceImpl" >
<constructor-arg name="memberRepository" ref="memberRepository" />
</bean>
<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/>
</beans>
ํ์์ชฝ(memberService์ memberRepository) ๋น์ ์ถ๊ฐํ์ต๋๋ค.
class๋ ๊ฒฝ๋ก๋ฅผ ๋ค ์ ์ด์ผ ํฉ๋๋ค.
์ฃผ๋ฌธ์ชฝ ๋น์ ์ถ๊ฐํด๋ณด๊ฒ ์ต๋๋ค.
<bean id="orderService" class="hello.core.order.OrderServiceImpl" >
<constructor-arg name="memberRepository" ref="memberRepository"/>
<constructor-arg name="discountPolicy" ref="discountPolicy" />
</bean>
<bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy" />
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ๋ค ์ง๋์ผ๋ฉด test์์ GenericXmlApplicationContext๊ฐ appConfig.xml์ ์ถ๊ฐํ ๋ด์ฉ์ ๋์ด๋ค๊ฐ ๋์ํ๊ฒ ๋ฉ๋๋ค.
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
ํ ์คํธ ์ฑ๊ณตํ์ต๋๋ค.
<์ ๋ฆฌโ๏ธ>
- xml ๊ธฐ๋ฐ์ appConfig.xml ์คํ๋ง ์ค์ ์ ๋ณด์ ์๋ฐ ์ฝ๋๋ก ๋ AppConfig.java ์ค์ ์ ๋ณด๋ฅผ ๋น๊ตํด๋ณด๋ฉด ๊ฑฐ์ ๋น์ทํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
- xml ๊ธฐ๋ฐ์ผ๋ก ์ค์ ํ๋ ๊ฒ์ ์ต๊ทผ์ ์ ์ฌ์ฉํ์ง ์์ผ๋ฏ๋ก ์ด ์ ๋๋ก ๋ง๋ฌด๋ฆฌ ํ๊ณ , ํ์ํ๋ฉด ์คํ๋ง ๊ณต์ ๋ ํผ๋ฐ์ค ๋ฌธ์๋ฅผ ํ์ธํด๋ณด๋ฉด ๋ฉ๋๋ค.
https://spring.io/projects/spring-framework

6. ์คํ๋ง ๋น ์ค์ ๋ฉํ ์ ๋ณด - BeanDefinition
์คํ๋ง์ ์ด๋ป๊ฒ ์ด๋ฐ ๋ค์ํ ์ค์ ํ์์ ์ง์ํ๋ ๊ฒ์ผ๊น์?
๊ทธ ์ค์ฌ์๋ BeanDefinition์ด๋ผ๋ ์ถ์ํ๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ฝ๊ฒ ์๊ธฐํด์ ์ญํ ๊ณผ ๊ตฌํ์ ๊ฐ๋ ์ ์ผ๋ก ๋๋ ๊ฒ์ ๋๋ค.
XML์ ์ฝ์ด์ BeanDefinition์ ๋ง๋ค๋ฉด ๋๊ณ , ์๋ฐ ์ฝ๋๋ฅผ ์ฝ์ด์ BeanDefinition์ ๋ง๋ค๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์คํ๋ง ์ปจํ ์ด๋ ์ ์ฅ์์๋ ์๋ฐ ์ฝ๋์ธ์ง, XML์ธ์ง ๋ชฐ๋ผ๋ ๋ฉ๋๋ค. ์ค์ง BeanDefinition๋ง ์๋ฉด ๋ฉ๋๋ค.
์ด๊ฒ์ ๊ธฐ๋ฐ์ผ๋ก ๋น์ ์์ฑํ๋ ๊ฒ์ ๋๋ค.
์ด BeanDefinition์ ๋น ์ค์ ๋ฉํ ์ ๋ณด๋ผ๊ณ ํฉ๋๋ค.
@Bean, <bean> ํ๋๋น ๊ฐ๊ฐ ํ๋์ฉ ๋ฉํ ์ ๋ณด๊ฐ ์์ฑ๋ฉ๋๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ์ด ๋ฉํ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํ๋ง ๋น์ ์์ฑํฉ๋๋ค.
์คํ๋ง ์ปจํ ์ด๋ ์์ฒด๋ BeanDefinition์๋ง ์์กดํฉ๋๋ค.
์๊ฐ class๋ก ์ค์ ๋ ์ ๋ณด์ธ์ง, xml๋ก ์ค์ ๋ ์ ๋ณด์ธ์ง, ์์๋ก ์ค์ ๋ ์ ๋ณด์ธ์ง ์๊ด์ ํ์ง ์๋ ๊ฒ์ ๋๋ค.
๊ฒฐ๊ตญ ๋ณด๋ฉด BeanDefinition ์์ฒด๊ฐ ์ธํฐํ์ด์ค์ ๋๋ค.
์ฝ๋ ๋ ๋ฒจ๋ก ์กฐ๊ธ ๋ ๊น์ด ์๊ฒ ๋ค์ด๊ฐ๋ณด๊ฒ ์ต๋๋ค.
์ด๊ฑฐ ๊ทธ๋ฆผ์ ๊ฑ ๊น์ด ์๊ฒ ์๋ฉด ์ข์๊ฑฐ๊ณ , ๋ชฐ๋ผ๋ ๋ฉ๋๋ค.
๋ชฐ๋ผ๋ ์คํ๋ง ๊ฐ๋ฐํ๋ ๋ฐ์ ์ ํ ์ง์ฅ ์์ต๋๋ค.
AnnotationConfigApplicationContext๋ AnnotatedBeanDefinitionReader๋ฅผ ์ฌ์ฉํด์ AppConfig.class๋ฅผ ์ฝ๊ณ BeanDefinition์ ์์ฑํฉ๋๋ค.
GenericXmlApplicationContext๋ XmlBeanDefinitionReader๋ฅผ ์ฌ์ฉํด์ appConfig.xml ์ค์ ์ ๋ณด๋ฅผ ์ฝ๊ณ , BeanDefinition์ ์์ฑํฉ๋๋ค.
๋ฐ๋ผ์, ์๋ก์ด ํ์์ ์ค์ ์ ๋ณด๊ฐ ์ถ๊ฐ ๋๋ฉด, XxxBeanDefinitionReader๋ฅผ ๋ง๋ค์ด์ BeanDefinition์ ์์ฑํ๋ฉด ๋ฉ๋๋ค.
6-1. BeanDefinition ์ดํด๋ณด๊ธฐ
<BeanDefinition ์ ๋ณดโญ>
- BeanClassName: ์์ฑํ ๋น์ ํด๋์ค ๋ช (์๋ฐ ์ค์ ์ฒ๋ผ factory ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฉด ์์)
- factoryBeanName: factory ์ญํ ์ ๋น์ ์ฌ์ฉํ ๊ฒฝ์ฐ์ ์ด๋ฆ (ex - appConfig)
- factoryMethodName: ๋น์ ์์ฑํ factory ๋ฉ์๋ ์ง์ (ex - memberService)
- Scope: ์ฑ๊ธํค (๊ธฐ๋ณธ๊ฐ)
- lazyInit: ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๋, ๋น์ ์์ฑํ๋ ๊ฒ์ด ์๋ ์ค์ ๋น์ ์ฌ์ฉํ ๋๊น์ง ์ต๋ํ ์์ฑ์ ์ง์ฐ์ฒ๋ฆฌ ํ๋์ง์ ์ฌ๋ถ
- InitMethodName: ๋น์ ์์ฑํ๊ณ , ์์กด ๊ด๊ณ๋ฅผ ์ ์ฉํ ๋ค์ ํธ์ถ๋๋ ์ด๊ธฐํ ๋ฉ์๋ ์ด๋ฆ
- DestoryMethodName: ๋น์ ์๋ช ์ฃผ๊ธฐ๊ฐ ๋๋์ ์ ๊ฑฐํ๊ธฐ ์ง์ ์ ํธ์ถ๋๋ ๋ฉ์๋ ์ด๋ฆ
- Constructor arguments, Properties: ์์กด ๊ด๊ณ ์ฃผ์ ์์ ์ฌ์ฉ (์๋ฐ ์ค์ ์ฒ๋ผ factory ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฉด ์์)
์ด๊ฒ ๊ทผ๋ฐ ๋ง๋ก๋ง ๋ณด๋ฉด ์ดํด๊ฐ ์ ์ ๊ฐ ์ ์์ต๋๋ค.
๊ทธ๋์, ์ฝ๋๋ก ํ ๋ฒ ๋ ๋ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
test ํจํค์ง์ hello.core์์ beandefinition์ด๋ผ๋ ํจํค์ง๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์ด ํจํค์ง ์์ BeanDefinitionTest๋ผ๋ ์๋ฐ ํด๋์ค๋ฅผ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
๋น ์ค์ ๋ฉํ์ ๋ณด๋ฅผ ํ์ธํ๋ ํ ์คํธ ์ ๋๋ค.
public class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋น ์ค์ ๋ฉํ์ ๋ณด ํ์ธ")
void findApplicationBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
System.out.println("beanDefinitionName = " + beanDefinitionName +
" beanDefinition = " + beanDefinition);
}
}
}
}
ํ ์คํธ๋ฅผ ์คํํด๋ณด๊ฒ ์ต๋๋ค.
์ด ๊ฒฐ๊ณผ์์ memberService์ memberRepository๋ฅผ ๋ด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ฑ์ ์ซ ๋ด๋ณด๋ฉด scope๋ผ๋ ๊ฒ ์๋๋ฐ ์ฌ๊ธฐ์ ํ ๋น์ด ๋์ด์์ง ์๋ค์. (ํ ๋น์ด ๋์ด์์ง ์์ผ๋ฉด ์ฑ๊ธํค์ด๋ผ๊ณ ํฉ๋๋ค.)
abstract๋ ์ถ์, lazyInit์ ์คํ๋ง ๋น์ ์ค์ ์ฌ์ฉํ ์์ ์ ์ด๊ธฐํํ๋ผ๋ ์ ๋ณด์ ๋๋ค.
์ด ์ธ์๋ ๋ค์ํ ์ ๋ณด๊ฐ ์์ผ๋ฉด ์์ ์๋ ์ ๋ณด๋ค ์ฐธ๊ณ ํ๋ฉด ๋ฉ๋๋ค.
๊ทธ๋ฅ ์ง๊ธ์ ์ด๋ฐ ์ข ๋ฅ์ ๋ฉํ ์ ๋ณด๊ฐ ์๋ค ์ ๋๋ก ์์๋๋ฉด ๋๊ณ , ์ด๋ฐ ๋ฉํ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ ์ ์๋ค๋ ๊ฒ์ ์์๋๋ฉด ๋ฉ๋๋ค.
<์ ๋ฆฌโ๏ธ>
- BeanDefinition์ ์ง์ ์์ฑํด์ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋กํ ์๋ ์์ต๋๋ค.
=> ํ์ง๋ง, ์ค๋ฌด์์ BeanDefinition์ ์ง์ ์ ์ํ๊ฑฐ๋ ์ฌ์ฉํ ์ผ์ ๊ฑฐ์ ์์ต๋๋ค.
- BeanDefinition์ ๋ํด์๋ ๋๋ฌด ๊น์ด ์ดํดํ๊ธฐ ๋ณด๋ค๋ ์คํ๋ง์ด ๋ค์ํ ํํ์ ์ค์ ์ ๋ณด๋ฅผ BeanDefinition์ผ๋ก ์ถ์ํํด์ ์ฌ์ฉํ๋ ๊ฒ ์ ๋๋ง ์ดํดํ๋ฉด ๋ฉ๋๋ค.
- ๊ฐ๋ ์คํ๋ง ์ฝ๋๋ ์คํ๋ง ๊ด๋ จ ์คํ ์์ค์ ์ฝ๋๋ฅผ ๋ณผ ๋, BeanDefinition์ด๋ผ๋ ๊ฒ์ด ๋ณด์ผ ๋๊ฐ ์์ต๋๋ค.
์ด ๋, ์ด๋ฐ ๋ฉ์ปค๋์ฆ์ ๋ ์ฌ๋ฆฌ๋ฉด ๋ฉ๋๋ค.
์ค๋ ๊ณต๋ถ๋ ์ด๋ ๊ฒ ๋์ด ๋ฌ์ต๋๋ค.
๋ค์์๋ ์ฑ๊ธํค์ ๊ดํด์ ๊ณต๋ถํ ์์ ์ ๋๋ค.
๊ทธ๋ผ ์๋ฝ!
