๐๏ธ ๋ณธ ํฌ์คํธ๋ ์ธํ๋ฐ ๊น์ํ ์คํ๋ง ๊ธฐ๋ณธํธ์ ๋ณด๊ณ ์ ๋ฆฌํ ๋ด์ฉ์ ๋๋ค.
์คํ๋ง ํต์ฌ ์๋ฆฌ - ๊ธฐ๋ณธํธ| ๊น์ํ - ์ธํ๋ฐ ๊ฐ์
ํ์ฌ ํ์ 5.0์ ์๊ฐ์ 48,207๋ช ์ธ ๊ฐ์๋ฅผ ๋ง๋๋ณด์ธ์. ์คํ๋ง ์ ๋ฌธ์๊ฐ ์์ ๋ฅผ ๋ง๋ค์ด๊ฐ๋ฉด์ ์คํ๋ง์ ํต์ฌ ์๋ฆฌ๋ฅผ ์ดํดํ๊ณ , ์คํ๋ง ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํ์คํ ๋ค์ง ์ ์์ต๋๋ค. ์คํ๋ง ๊ธฐ๋ณธ ๊ธฐ๋ฅ, ์คํ
www.inflearn.com

์คํ๋ง ์ปจํ ์ด๋ ์์ฑ
//์คํ๋ง ์ปจํ
์ด๋ ์์ฑ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext
- ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ํ๋ฉฐ ์ธํฐํ์ด์ค๋ค.
- ์คํ๋ง ์ปจํ ์ด๋๋ xml์ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค ์ ์๊ณ ์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ ์๋ฐ ์ค์ ํด๋์ค๋ก ๋ง๋ค ์ ์๋ค.
- ์คํ๋ง ์ปจํ ์ด๋๋ @Component, @Configuration, @Bean ๊ฐ์ ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ํด๋์ค๋ฅผ ์ฝ์ด์, ํ์ํ ๊ฐ์ฒด๋ค(๋น, Bean)์ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉฐ, ๊ฐ์ฒด๋ค ๊ฐ์ ์์กด๊ด๊ณ๋ฅผ ์๋์ผ๋ก ์ฐ๊ฒฐํด์ฃผ๋ ์ญํ ์ ํ๋ค.
์ง์ ์ค์ต์์ AppConfig.๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ์์ด ์ด๋ ธํ ์ด์ ๊ธฐ๋ฐ์ ์๋ฐ ์ค์ ํด๋์ค๋ก ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ๋ง๋ ๊ฒ
์คํ๋ง ์ปจํ ์ด๋์ ์์ฑ ๊ณผ์
1. ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ

'
- ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๋๋ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ง์ ํด์ฃผ์ด์ผํ๋ค. (์ฌ๊ธฐ์๋ AppConfig.class ๋ฅผ ๊ตฌ์ฑ ์ ๋ณด๋ก ์ง์ ํ๋ค)
2. ์คํ๋ง ๋น ๋ฑ๋ก

- ์คํ๋ง ์ปจํ ์ด๋๋ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ ์ค์ ํด๋์ค ์ ๋ณด๋ฅผ ์ฌ์ฉํด์ ์คํ๋ง ๋น์ ๋ฑ๋กํ๋ค
- @Bean ์ด๋ ธํ ์ด์ ์ด ๋ถ์ ๋ฉ์๋๋ ์คํ๋ง ๋น์ ๋ฑ๋กํ๋ ๋ฉ์๋๋ก ์ธ์ํ๋ค.
- ์ฌ๊ธฐ์ @x01, @x02๋ ๋จ์ํ ๊ฐ์ฒด์ ๋ฉ๋ชจ๋ฆฌ ์์น(์ฃผ์๊ฐ)๋ฅผ ํํํ ๊ฒ
โ ๏ธ์ฃผ์
๋น ์ด๋ฆ์ ํญ์ ๋ค๋ฅธ ์ด๋ฆ์ ๋ถ์ฌํด์ผํ๋ค
๋์ผํ ์ด๋ฆ์ ๋น์ด ๋ฑ๋ก๋๋ฉด ๊ธฐ์กด ๋น์ ๋ฎ์ด์ฐ๊ฑฐ๋(BeanDefinitionOverride), ์ถฉ๋ ์์ธ๊ฐ ๋ฐ์ํ ์ ์๋ค.
3. ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์ค๋น

- memberService๋ฅผ ์์ฑํ ๋ memberRepository() ํ์
- orderService๋ฅผ ์์ฑํ ๋ memberRepository(), discountPolicy() ํ์
4. ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์๋ฃ

- ์ด์ ์คํ๋ง ์ปจํ ์ด๋๊ฐ AppConfig ์ค์ ์ ๋ณด๋ฅผ ์ด์ฉํด ์ค์ ์์กด์ฑ์ ์ฃผ์ (DI, Dependency Injection)ํ๋ค
- ๊ฐ ์๋น์ค๊ฐ ํ์๋ก ํ๋ ๊ฐ์ฒด๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์ฐพ์์ ์๋์ผ๋ก ์ฐ๊ฒฐํด ์ค๋ค.
์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์กฐํ
package hello.core.beanfind;
import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new
AnnotationConfigApplicationContext(AppConfig.class); // 1. ์ปจํ
์ด๋ ์์ฑ
@Test
@DisplayName("๋ชจ๋ ๋น ์ถ๋ ฅํ๊ธฐ")
void findAllBean() { //2. ๋ชจ๋ ๋น ์ถ๋ ฅํ๊ธฐ
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name=" + beanDefinitionName + " object=" +
bean);
}
}
@Test
@DisplayName("์ ํ๋ฆฌ์ผ์ด์
๋น ์ถ๋ ฅํ๊ธฐ")
void findApplicationBean() { //3. ์ ํ๋ฆฌ์ผ์ด์
๋น ์ถ๋ ฅํ๊ธฐ
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition =
ac.getBeanDefinition(beanDefinitionName);
//Role ROLE_APPLICATION: ์ง์ ๋ฑ๋กํ ์ ํ๋ฆฌ์ผ์ด์
๋น
//Role ROLE_INFRASTRUCTURE: ์คํ๋ง์ด ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋น
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name=" + beanDefinitionName + " object=" + bean);
}
}
}
}
๋ชจ๋ ๋น์ถ๋ ฅํ๊ธฐ
- ac.getBeanDefinitionNames() → ํ์ฌ ์คํ๋ง ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์ด๋ฆ์ ๊ฐ์ ธ์จ๋ค.
- ac.getBean(beanDefinitionName) → ํด๋น ๋น ์ด๋ฆ์ผ๋ก ์ค์ ๋น ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์จ๋ค.
- ๋ฐ๋ผ์ ์คํ ๊ฒฐ๊ณผ๋ ๋ด๊ฐ ๋ฑ๋กํ ๋น + ์คํ๋ง ๋ด๋ถ์์ ๋ฑ๋กํ ๋น๊น์ง ๋ชจ๋ ์ถ๋ ฅ๋๋ค
์ ํ๋ฆฌ์ผ์ด์ ๋น ์ถ๋ ฅํ๊ธฐ
- BeanDefinition ๊ฐ์ฒด๋ฅผ ํตํด ๋น์ ์ญํ (Role)์ ํ์ธํ๋ค.
- ์คํ๋ง ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋น์ getRole() ๊ฐ์ผ๋ก ๊ตฌ๋ถํ ์ ์๋ค
- ROLE_APPLICATION → ๊ฐ๋ฐ์๊ฐ ์ง์ ๋ฑ๋กํ ๋น (AppConfig์์ ๋ง๋ ๊ฒ๋ค)
- ROLE_INFRASTRUCTURE → ์คํ๋ง ๋ด๋ถ ๋์์ ์ํด ๋ฑ๋ก๋ ๋น (์: ์๋ ํ๋ก์ ์์ฑ๊ธฐ ๋ฑ)
- ๋ฐ๋ผ์ ์คํ๊ฒฐ๊ณผ๋ ๋ด๊ฐ ๋ฑ๋กํ ๋น๋ง ์ถ๋ ฅ๋๋ค
์คํ๊ฒฐ๊ณผ
Starting Gradle Daemon...
Gradle Daemon started in 1 s 398 ms
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
name=appConfig object=hello.core.AppConfig$$SpringCGLIB$$0@70e659aa
name=memberService object=hello.core.member.MemberServiceImpl@2ef8a8c3
name=orderService object=hello.core.order.OrderServiceImpl@24f43aa3
name=memberRepository object=hello.core.member.MemoryMemberRepository@63fd4873
name=discountPolicy object=hello.core.discount.RateDiscountPolicy@1e11bc55
name=org.springframework.context.annotation.internalConfigurationAnnotationProcessor object=org.springframework.context.annotation.ConfigurationClassPostProcessor@77b21474
name=org.springframework.context.annotation.internalAutowiredAnnotationProcessor object=org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@52d10fb8
name=org.springframework.context.annotation.internalCommonAnnotationProcessor object=org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@41c07648
name=org.springframework.context.event.internalEventListenerProcessor object=org.springframework.context.event.EventListenerMethodProcessor@1fe8d51b
name=org.springframework.context.event.internalEventListenerFactory object=org.springframework.context.event.DefaultEventListenerFactory@781e7326
name=appConfig object=hello.core.AppConfig$$SpringCGLIB$$0@22680f52
name=memberService object=hello.core.member.MemberServiceImpl@60d84f61
name=orderService object=hello.core.order.OrderServiceImpl@39c11e6c
name=memberRepository object=hello.core.member.MemoryMemberRepository@324dcd31
name=discountPolicy object=hello.core.discount.RateDiscountPolicy@503d56b5
> Task :test
BUILD SUCCESSFUL in 10s
์คํ๋ง ๋น ์กฐํ - ๊ธฐ๋ณธ
์คํ๋ง ๋น ์กฐํ ๊ธฐ๋ณธ ๋ฐฉ๋ฒ
์คํ๋ง ์ปจํ ์ด๋์์ ์คํ๋ง ๋น์ ์ฐพ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์กฐํ ๋ฐฉ๋ฒ
- ac.getBean(๋น์ด๋ฆ, ํ์ )
- ac.getBean(ํ์ )
1. ๋น ์ด๋ฆ + ํ์ ์ผ๋ก ์กฐํ
MemberService memberService = ac.getBean("memberService", MemberService.class);
- "memberService" → ์คํ๋ง ๋น ์ด๋ฆ (๋ฉ์๋ ์ด๋ฆ์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๋น ์ด๋ฆ์ด ๋จ)
- MemberService.class → ๋น์ ํ์
- ์ฅ์ : ๋์ผ ํ์ ์ ๋น์ด ์ฌ๋ฌ ๊ฐ ์์ด๋, ์ด๋ฆ์ผ๋ก ๊ตฌ๋ถ ๊ฐ๋ฅ
- ๋จ์ : ์ด๋ฆ์ด ํ๋ฆฌ๋ฉด NoSuchBeanDefinitionException ๋ฐ์
2. ํ์ ์ผ๋ก๋ง์กฐํ
MemberService memberService = ac.getBean(MemberService.class);
- ๋น ์ด๋ฆ์ ์๋ตํ๊ณ ํ์ ๋ง์ผ๋ก ์กฐํ ๊ฐ๋ฅ
- ๊ฐ์ ํ์ ์ ๋น์ด ํ๋๋ง ์์ ๋ ์ฌ์ฉ ๊ฐ๋ฅ
- ๊ฐ์ ํ์ ์ ๋น์ด ๋ ์ด์ ์์ผ๋ฉด NoUniqueBeanDefinitionException ๋ฐ์
3. ์กฐํ ๋์ ์คํ๋ง ๋น์ด ์์ผ๋ฉด?
๋ค์๊ณผ ๊ฐ์ด ์์ธ๊ฐ ๋ฐ์ํ๋ค
NoSuchBeanDefinitionException: No bean named 'xxxxx' available
์ค์ต ์์ ์ฝ๋
package hello.core.beanfind;
import hello.core.AppConfig;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.*;
class ApplicationContextBasicFindTest {
AnnotationConfigApplicationContext ac=new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ")
void findBeanByName(){
MemberService memberService=ac.getBean("memberService",MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class); //memberService ๊ฐ์ฒด๊ฐ MemberServiceImpl ํด๋์ค์ ์ธ์คํด์ค์ธ์ง ํ์ธ
}
@Test
@DisplayName("์ด๋ฆ ์์ด ํ์
๋ง์ผ๋ก ์กฐํ")
void findBeanByType(){
MemberService memberService=ac.getBean("memberService",MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("๊ตฌ์ฒด ํ์
์ผ๋ก ์กฐํ")
void findBeanByName2() {
MemberServiceImpl memberService = ac.getBean("memberService",
MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ X")
void findBeanByNameX(){
//ac.getBean("xxxxx", MemberService.class);
Assertions.assertThrows(NoSuchBeanDefinitionException.class,() -> ac.getBean("xxxxx",MemberService.class));
}
}
ac.getBean(...)
- ์คํ๋ง ์ปจํ ์ด๋์์ ๋น์ ๊บผ๋ด์ค๋ ๋ฉ์๋
assertThat(...)
- AssertJ๋ผ๋ ํ ์คํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ ๊ณตํ๋ ๋ฉ์๋.
- JUnit๊ณผ ํจ๊ป ์์ฃผ ์ฐ์.
.isInstanceOf(MemberServiceImpl.class)
- memberService ๊ฐ์ฒด๊ฐ MemberServiceImpl ํด๋์ค์ ์ธ์คํด์ค์ธ์ง ํ์ธ.
- (์ฆ, memberService๊ฐ ์ ๋ง ๊ตฌํ์ฒด MemberServiceImpl๋ก ์์ฑ๋์๋์ง ๊ฒ์ฆํ๋ ๊ฒ)
| ํ ์คํธ ๋ฉ์๋ | ์กฐํ ๊ธฐ์ค | ๋ฐํ ํ์ | ์กฐํ ๋ฐฉ์ |
| findBeanByName | "memberService" + MemberService.class | MemberService | ์ธํฐํ์ด์ค ํ์ ์กฐํ |
| findBeanByType | MemberService.class | MemberService | ์ธํฐํ์ด์ค ํ์ ์กฐํ |
| findBeanByName2 | "memberService" + MemberServiceImpl.class | MemberServiceImpl | ๊ตฌ์ฒด ํ์ ์กฐํ |
์ฐธ๊ณ
๊ตฌ์ฒด ํ์ ์ผ๋ก ์กฐํํ๋ฉด ๋ณ๊ฒฝ์ ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ค.
์คํ๋ง ๋น ์กฐํ - ๋์ผํ ํ์ ์ด ๋ ์ด์
ํ์ ์ผ๋ก ์กฐํ ์ ๊ฐ์ ํ์ ์ ์คํ๋ง ๋น์ด ๋ ์ด์์ด๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ -> ์ด๋ ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด๋๋ค
ac.getBeansOfType()์ ์ฌ์ฉํ๋ฉด ํด๋น ํ์ ์ ๋ชจ๋ ๋น์ ์กฐํํ ์ ์๋ค
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด, ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค")
void findBeanByTypeDuplicate() {
//MemberRepository bean = ac.getBean(MemberRepository.class);
assertThrows(NoUniqueBeanDefinitionException.class, () ->
ac.getBean(MemberRepository.class));
}
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด, ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋๋ค")
void findBeanByName() {
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
@Test
@DisplayName("ํน์ ํ์
์ ๋ชจ๋ ์กฐํํ๊ธฐ")
void findAllBeanByType() {
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);
}
@Configuration
static class SameBeanConfig {
@Bean
public MemberRepository memberRepository1() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
Map<String, MemberRepository>
- key → ๋น ์ด๋ฆ ("memberRepository1", "memberRepository2" ๋ฑ)
- value → ๋น ๊ฐ์ฒด (MemoryMemberRepository, JdbcMemberRepository ๊ฐ์ ๊ตฌํ์ฒด ์ธ์คํด์ค)
@Configuration ์คํ๋ง ์ปจํ ์ด๋์ ๋น์ ๋ฑ๋กํ๊ธฐ ์ํ ์ค์ ํด๋์ค์์ ํ์ํ๋ ์ด๋ ธํ ์ด์
์คํ๊ฒฐ๊ณผ
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
key = memberRepository1 value = hello.core.member.MemoryMemberRepository@41c07648
key = memberRepository2 value = hello.core.member.MemoryMemberRepository@2d35442b
beansOfType = {memberRepository1=hello.core.member.MemoryMemberRepository@41c07648, memberRepository2=hello.core.member.MemoryMemberRepository@2d35442b}
> Task :test
BUILD SUCCESSFUL in 3s
4 actionable tasks: 2 executed, 2 up-to-date
์คํ 8:54:12: Execution finished ':test --tests "hello.core.beanfind.ApplicationContextSameBeanFindTest"'.
์คํ๋ง ๋น ์กฐํ - ์์ ๊ด๊ณ
์คํ๋ง ๋น์ ์๋ฐ ๊ฐ์ฒด๋๊น, ์์ ๊ตฌ์กฐ๋ฅผ ๊ทธ๋๋ก ๋ฐ๋ฅธ๋ค. ๋ฐ๋ผ์ ๋ถ๋ชจ ํ์ ์ผ๋ก ์กฐํํ๋ฉด, ๊ทธ ๋ถ๋ชจ๋ฅผ ์์ํ๊ฑฐ๋ ๊ตฌํํ ์์ ํ์ ๋น๋ค๋ ํจ๊ป ์กฐํ๋๋ค. ๋ชจ๋ ์๋ฐ ๊ฐ์ฒด์ ์ต๊ณ ๋ถ๋ชจ์ธ Object ํ์ ์ผ๋ก ์กฐํํ๋ฉด, ๋ชจ๋ ์คํ๋ง ๋น์ ์กฐํํ๋ค.
@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));
}
}
ac.getBeansOfType(DiscountPolicy.class)
- DiscountPolicy๋ ์ธํฐํ์ด์ค (๋ถ๋ชจ ํ์ ).
- ์ปจํ ์ด๋์ ๋ฑ๋ก๋ DiscountPolicy๋ฅผ ๊ตฌํํ ๋ชจ๋ ๋น์ Map์ผ๋ก ๋ฐํ.
assertThat(beansOfType.size()).isEqualTo(2);
- ์ปจํ ์ด๋์ DiscountPolicy ๊ตฌํ์ฒด ๋น์ด 2๊ฐ ๋ฑ๋ก๋์ด ์๋ค๊ณ ๊ฐ์ ํ๋ ํ ์คํธ.
- ๋ณดํต AppConfig ๊ฐ์ ์ค์ ํด๋์ค์ ์ด๋ ๊ฒ ๋ฑ๋กํด๋๋ค.
์ ๋ฆฌ
- ๋ถ๋ชจ ํ์ (DiscountPolicy)์ผ๋ก ์กฐํํ๋ฉด, ์์ ํ์ (RateDiscountPolicy, FixDiscountPolicy) ๋น์ด ๋ชจ๋ ์กฐํ๋๋ค.
- ac.getBeansOfType(๋ถ๋ชจํ์ ) → ๋ฐํ: Map<String, ๋ถ๋ชจํ์ >
- ์ด ๋ฐฉ์์ผ๋ก ๋คํ์ฑ์ ํ์ฉํ ๋น ์กฐํ๊ฐ ๊ฐ๋ฅํ๋ค.
BeanFactory์ ApplicationContext

BeanFactory
1. ์คํ๋ง ์ปจํ ์ด๋์ ์ต์์ ์ธํฐํ์ด์ค๋ค.
2. ์คํ๋ง ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ์ญํ ์ ๋ด๋นํ๋ค.
- ๋น ๊ด๋ฆฌ (Bean Lifecycle ๊ด๋ฆฌ)
- @Bean์ด๋ @Component๋ก ์ ์๋ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ์ปจํ ์ด๋์ ๋ด์ ๊ด๋ฆฌ
- ์ฑ๊ธํค ๋ณด์ฅ: ๊ฐ์ ๋น ์์ฒญ์ด ์ค๋ฉด ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ๋ฐํ
- ์์กด๊ด๊ณ ์ฃผ์ (DI): ํ์ํ ๋น์ ์ฐพ์์ ๋ค๋ฅธ ๋น์ ์ฃผ์
- ๋น ์กฐํ (Lookup)
- getBean(String name)
- getBean(Class<T> requiredType)
→ ์ด๋ฆ ๋๋ ํ์ ์ผ๋ก ๋น์ ๊ฒ์ํด ๋ฐํ
3. IoC(์ ์ด์ ์ญ์ ) ์ปจํ ์ด๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ํต์ฌ ๋ผ๋
4. ์ค๋ฌด์์๋ ์ ์ ์. ๋ณดํต ApplicationContext๋ฅผ ์ด๋ค,
ApplicationContext
1. ์ฐ๋ฆฌ๊ฐ ์ฐ๋ ApplicationContext๋ ๊ฒฐ๊ตญ BeanFactory๋ฅผ ์์๋ฐ์ ๊ตฌํ๋ ๊ฒ์ด๋ค.
2. ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋๋ ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ฌผ๋ก ์ด๊ณ , ์ ๋ง์ ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํ์ํ๋ฐ ApplicationContext๊ฐ ์ด๋ฅผ ์ ๊ณตํ๋ค.
ApplicatonContext๊ฐ ์ ๊ณตํ๋ ๋ถ๊ฐ๊ธฐ๋ฅ
1. ๋ฉ์์ง ์์ค (MessageSource) → ๊ตญ์ ํ(i18n)
- ์ฌ๋ฌ ์ธ์ด ์ง์
- ๊ฐ์ ์ฝ๋๋ผ๋ ์ฌ์ฉ์์ Locale(๊ตญ๊ฐ/์ธ์ด ์ค์ )์ ๋ฐ๋ผ ๋ค๋ฅธ ๋ฉ์์ง ์ถ๋ ฅ
String message = context.getMessage("hello", null, Locale.KOREA);
// "์๋
ํ์ธ์" ์ถ๋ ฅ
String message = context.getMessage("hello", null, Locale.ENGLISH);
// "Hello" ์ถ๋ ฅ
2. ํ๊ฒฝ ๋ณ์ (EnvironmentCapable)
- ๋ก์ปฌ / ๊ฐ๋ฐ / ์ด์ ํ๊ฒฝ ๊ตฌ๋ถ
- ์ด์ ํ๊ฒฝ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ค์ ๊ฐ์ ์ฃผ์
๊ฐ๋ฅ
Environment env = context.getEnvironment();
System.out.println(env.getProperty("spring.datasource.url"));
-> application-local.properties, application-dev.properties ๊ฐ์ ํ๋กํ ๊ธฐ๋ฐ ์ค์ ๋ ๊ฐ๋ฅ
3. ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฒคํธ (ApplicationEventPublisher)
- ์ด๋ฒคํธ ๋ฐํ / ๊ตฌ๋ ๋ชจ๋ธ ์ง์
- ์ต์ ๋ฒ ํจํด์ ์คํ๋ง์ด ์ง์ ๊ตฌํํด์ค
// ์ด๋ฒคํธ ๋ฐํ
context.publishEvent(new MyCustomEvent(this, "์ด๋ฒคํธ ๋ฐ์"));
// ์ด๋ฒคํธ ๋ฆฌ์ค๋
@Component
public class MyEventListener {
@EventListener
public void handle(MyCustomEvent event) {
System.out.println("์ด๋ฒคํธ ์์ : " + event.getMessage());
}
}
4. ๋ฆฌ์์ค ๋ก๋ฉ (ResourceLoader)
- ๋ค์ํ ๋ฆฌ์์ค ์ ๊ทผ์ ์ผ๊ด๋๊ฒ ์ง์
- ํ์ผ ์์คํ , ํด๋์คํจ์ค, ์ธ๋ถ URL ๋ฑ
Resource resource = context.getResource("classpath:application.properties");
System.out.println(resource.getFilename()); // application.properties