[์คํ๋ง ๊ธฐ๋ณธ] 04. ์คํ๋ง ์ปจํ ์ด๋์ ์คํ๋ง ๋น
by Hi.Claire๐ฅ๏ธ ์คํ๋ง ํต์ฌ ์๋ฆฌ - ๊ธฐ๋ณธํธ (๊น์ํ, ์ธํ๋ฐ)
์น์ 4. ์คํ๋ง ์ปจํ ์ด๋์ ์คํ๋ง ๋น
04-1. ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ ํ๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ XML์ ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค ์๋ ์๊ณ , ์ ๋ ธํ ์ด์ ๊ธฐ๋ฐ์ ์๋ฐ ์ค์ ํด๋์ค(์ : AppConfig)๋ก ๋ง๋ค ์๋ ์๋ค.
์์ ์ฝ๋์์ ApplicationContext๋ ์ธํฐํ์ด์ค์ด๊ณ , AnnotationConfigApplicationContext๋ ํด๋น ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด์ด๋ค.
(์ฐธ๊ณ ) ๋ ์ ํํ๋ ์คํ๋ง ์ปจํ ์ด๋๋ฅผ ๋ถ๋ฅผ ๋ BeanFactory์ ApplicationContext๋ก ๊ตฌ๋ถํด์ ์ด์ผ๊ธฐํ๋ค. BeanFactory๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์์ผ๋ฏ๋ก ์ผ๋ฐ์ ์ผ๋ก ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ ํ๋ค.
์คํ๋ง ์ปจํ ์ด๋์ ์์ฑ ๊ณผ์
1. ์คํ๋ง ์ปจํ ์ด๋ ์์ฑ
new AnnotationConfigApplicationContext(AppConfig.class)
์คํ๋ง ์ปจํ ์ด๋๋ฅผ ์์ฑํ ๋ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ง์ ํด์ฃผ์ด์ผ ํ๋ค.
์ฌ๊ธฐ์๋ AppConfig.class๋ฅผ ๊ตฌ์ฑ ์ ๋ณด๋ก ์ง์ ํ๋ค.
2. ์คํ๋ง ๋น ๋ฑ๋ก
์คํ๋ง ์ปจํ ์ด๋๋ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ ์ค์ ํด๋์ค ์ ๋ณด๋ฅผ ์ฌ์ฉํด์ ์คํ๋ง ๋น์ ๋ฑ๋กํ๋ค.
๋น ์ด๋ฆ์ ๋ฉ์๋ ์ด๋ฆ์ ์ฌ์ฉํ๋ค.
๋ค์๊ณผ ๊ฐ์ด ๋น ์ด๋ฆ์ ์ง์ ๋ถ์ฌํ ์๋ ์๋ค.
@Bean(name="memberService2")
(์ฃผ์) ๋น ์ด๋ฆ์ ํญ์ ๋ค๋ฅธ ์ด๋ฆ์ ๋ถ์ฌํด์ผ ํ๋ค. ๊ฐ์ ์ด๋ฆ์ ๋ถ์ฌํ๋ฉด ๋ค๋ฅธ ๋น์ด ๋ฌด์๋๊ฑฐ๋, ๊ธฐ์กด ๋น์ ๋ฎ์ด๋ฒ๋ฆฌ๊ฑฐ๋, ์ค์ ์ ๋ฐ๋ผ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
3. ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์ค๋น
4. ์คํ๋ง ๋น ์์กด๊ด๊ณ ์ค์ - ์๋ฃ
์คํ๋ง ์ปจํ ์ด๋๋ ๊ตฌ์ฑ ์ ๋ณด๋ฅผ ์ฐธ๊ณ ํด์ ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ (DI)ํ๋ค.
์ด๊ฒ์ ๋จ์ํ ์๋ฐ ์ฝ๋๋ฅผ ํธ์ถํ๋ ๊ฒ๊ณผ๋ ์ฐจ์ด๊ฐ ์๋๋ฐ ๋์ค์ ์ฑ๊ธํค ์ปจํ ์ด๋์์ ์์๋ณด์.
(์ฐธ๊ณ ) ์คํ๋ง์ ์คํ๋ง ๋น์ ์์ฑํ๊ณ , ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ ํ๋ ๋จ๊ณ๊ฐ ๋๋์ด์ ธ ์๋ค. ๊ทธ๋ฐ๋ฐ ์์ ๊ฐ์ด ์๋ฐ ์ฝ๋๋ก ์คํ๋ง ๋น์ ๋ฑ๋กํ๋ฉด ์์ฑ์๋ฅผ ํธ์ถํ๋ฉด์ ์์กด๊ด๊ณ ์ฃผ์ ๋ ํ๋ฒ์ ์ฒ๋ฆฌ๋๋ค. ์์ธํ ๋ด์ฉ์ ์์กด๊ด๊ณ ์๋ ์ฃผ์ ์์ ๋ค์ ์์๋ณด์.
04-2. ์ปจํ ์ด๋์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์กฐํ
์ด์ ์คํ๋ง ์ปจํ ์ด๋์ ์ค์ ์คํ๋ง ๋น๋ค์ด ์ ๋ฑ๋ก๋์๋์ง ํ์ธํด๋ณด์.
test/java/hello/core/findbean/ApplicationContextInfoTest.java
package hello.core.findbean;
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;
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋ชจ๋ ๋น ์ถ๋ ฅํ๊ธฐ")
void findAllBeans() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + ", object = " + bean);
}
}
@Test
@DisplayName("์ ํ๋ฆฌ์ผ์ด์
๋น ์ถ๋ ฅํ๊ธฐ")
void findApplicationBeans() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
// BeanDefinition.ROLE_APPLICATION : ์ง์ ๋ฑ๋กํ ์ ํ๋ฆฌ์ผ์ด์
๋น
// BeanDefinition.ROLE_INFRASTRUCTURE : ์คํ๋ง์ด ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋น
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + ", object = " + bean);
}
}
}
}
ac.getBeanDefinitionNames() : ์คํ๋ง์ ๋ฑ๋ก๋ ๋ชจ๋ ๋น ์ด๋ฆ์ ์กฐํํ๋ค.
ac.getBean() : ๋น ์ด๋ฆ์ผ๋ก ๋น ๊ฐ์ฒด(์ธ์คํด์ค)๋ฅผ ์กฐํํ๋ค.
for๋ฌธ ์๋ ์์ฑ ๋จ์ถํค : iter + Tab
๋ณ์ ์ถ๋ ฅ ๋จ์ถํค : soutv + Enter
๋ฉ์๋ ์ถ๋ ฅ ๋จ์ถํค : soutm + Enter
04-3. ์คํ๋ง ๋น ์กฐํ - ๊ธฐ๋ณธ
์คํ๋ง ์ปจํ ์ด๋์์ ์คํ๋ง ๋น์ ์ฐพ๋ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ ์กฐํ ๋ฐฉ๋ฒ
1. ac.getBean(๋น์ด๋ฆ, ํ์ )
2. ac.getBean(ํ์ )
์ด๋, ์กฐํ ๋์ ์คํ๋ง ๋น์ด ์์ผ๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋ค.
NoSuchBeanDefinitionException: No bean named 'xxxxx' available`
test/java/hello/core/findbean/ApplicationContextBasicFindTest.java
package hello.core.findbean;
import hello.core.AppConfig;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.assertj.core.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.*;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextBasicFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํ")
void findBeanByName() {
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("ํ์
์ผ๋ก๋ง ์กฐํ")
void findBeanByType() {
MemberService memberService = ac.getBean(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() {
// MemberService memberService = ac.getBean("xxxxx", MemberService.class);
assertThrows(NoSuchBeanDefinitionException.class, () -> ac.getBean("xxxxx", MemberService.class));
}
}
(์ฐธ๊ณ ) ๊ตฌ์ฒด ํ์ ์ผ๋ก ์กฐํํ๋ฉด ์ญํ ์ด ์๋ ๊ตฌํ์ ์์กดํ๊ธฐ ๋๋ฌธ์ ๋ณ๊ฒฝ ์ ์ ์ฐ์ฑ์ด ๋จ์ด์ง๋ค.
04-4. ์คํ๋ง ๋น ์กฐํ - ๋์ผํ ํ์ ์ด ๋ ์ด์
ํ์ ์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์ ์ ์คํ๋ง ๋น์ด ๋ ์ด์์ด๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค.
NoUniqueBeanDefinitionException: No qualifying bean of type 'hello.core.member.MemberRepository' available: expected single matching bean but found 2: memberRepository1,memberRepository2
์ด๋๋ ๋น ์ด๋ฆ์ ์ง์ ํ์.
test/java/hello/core/findbean/ApplicationContextSameBeanFIndTest.java
package hello.core.findbean;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.lang.model.SourceVersion;
import java.util.Map;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextSameBeanFIndTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์กด์ฌํ๋ฉด ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค")
void findBeanByTypeDuplicate() {
// Object bean = ac.getBean(MemberRepository.class);
// assertThat(bean).isInstanceOf(MemberRepository.class);
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(MemberRepository.class));
}
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์กด์ฌํ๋ฉด ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋๋ค")
void findBeanByTypeAndName() {
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
@Test
@DisplayName("ํน์ ํ์
์ ๋น์ ๋ชจ๋ ์กฐํํ๊ธฐ")
void findAllBeansByType() {
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
MemberRepository memberRepository1() {
return new MemoryMemberRepository();
}
@Bean
MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
ac.getBeansOfType() : ํด๋น ํ์ ์ ๋ชจ๋ ๋น์ ์กฐํํ๋ค.
04-5. ์คํ๋ง ๋น ์กฐํ - ์์ ๊ด๊ณ
๋ถ๋ชจ ํ์ ์ผ๋ก ์กฐํํ๋ฉด ์์ ํ์ ๋ ํจ๊ป ์กฐํ๋๋ค.
๊ทธ๋์ ๋ชจ๋ ์๋ฐ ๊ฐ์ฒด์ ์ต๊ณ ๋ถ๋ชจ์ธ Object ํ์ ์ผ๋ก ์กฐํํ๋ฉด ๋ชจ๋ ์คํ๋ง ๋น์ ์กฐํํ๋ค.
test/java/hello/core/findbean/ApplicationContextExtendsFindTest.java
package hello.core.findbean;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ExtendsConfig.class);
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ์ ์์์ด ๋ ์ด์ ์กด์ฌํ๋ฉด ์ค๋ณต ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค")
void findBeanByParentTypeDuplicate() {
// DiscountPolicy discountPolicy = ac.getBean(DiscountPolicy.class);
// Assertions.assertThat(discountPolicy).isInstanceOf(DiscountPolicy.class);
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
}
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ์ ์์์ด ๋ ์ด์ ์กด์ฌํ๋ฉด ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋๋ค")
void findBeanByParentTypeAndName() {
DiscountPolicy fixDiscountPolicy = ac.getBean("fixDiscountPolicy", DiscountPolicy.class);
assertThat(fixDiscountPolicy).isInstanceOf(FixDiscountPolicy.class);
}
@Test
@DisplayName("ํน์ ํ์ ํ์
์ผ๋ก ์กฐํ")
void findBeanBySubType() {
RateDiscountPolicy rateDiscountPolicy = ac.getBean(RateDiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ๋ชจ๋ ์กฐํํ๊ธฐ")
void findAllBeansByParentType() {
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.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);
}
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ๋ชจ๋ ์กฐํํ๊ธฐ - Object")
void findAllBeansByObjectType() {
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + ", value = " + beansOfType.get(key));
}
System.out.println("beansOfType = " + beansOfType);
}
@Configuration
static class ExtendsConfig {
@Bean
DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
@Bean
DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
}
}
04-6. BeanFactory์ ApplicationContext
BeanFactory์ ApplicationContext์ ๋ํด์ ์์๋ณด์.
BeanFactory
- ์คํ๋ง ์ปจํ ์ด๋์ ์ต์์ ์ธํฐํ์ด์ค๋ค.
- ์คํ๋ง ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ์ญํ ์ ๋ด๋นํ๋ค.
- getBean()์ ์ ๊ณตํ๋ค.
- ์ง๊ธ๊น์ง ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ๋๋ถ๋ถ์ ๊ธฐ๋ฅ์ BeanFactory๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๋ค.
ApplicationContext
- BeanFactory์ ๊ธฐ๋ฅ์ ๋ชจ๋ ์์๋ฐ์์ ์ ๊ณตํ๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฐ๋ฐํ ๋์๋ ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ ์ธ์๋ ์ ๋ง์ ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํ์ํ๋ฐ, ApplicationContext๊ฐ ๊ทธ๋ฐ ๋ถ๊ฐ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
ApplicationContext๊ฐ ์ ๊ณตํ๋ ๋ถ๊ฐ๊ธฐ๋ฅ
1. ๋ฉ์์ง ์์ค๋ฅผ ํ์ฉํ ๊ตญ์ ํ ๊ธฐ๋ฅ
- ์๋ฅผ ๋ค์ด, ํ๊ตญ์์ ๋ค์ด์ค๋ฉด ํ๊ตญ์ด๋ก, ์์ด๊ถ์์ ๋ค์ด์ค๋ฉด ์์ด๋ก ์ถ๋ ฅ
2. ํ๊ฒฝ๋ณ์
- ๋ก์ปฌ, ๊ฐ๋ฐ, ์ด์ ํ๊ฒฝ ๋ฑ์ ๊ตฌ๋ถํด์ ์ฒ๋ฆฌ
3. ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฒคํธ
- ์ด๋ฒคํธ๋ฅผ ๋ฐํํ๊ณ ๊ตฌ๋ ํ๋ ๋ชจ๋ธ์ ํธ๋ฆฌํ๊ฒ ์ง์
4. ํธ๋ฆฌํ ๋ฆฌ์์ค ์กฐํ
- ํ์ผ, ํด๋์คํจ์ค, ์ธ๋ถ ๋ฑ์์ ๋ฆฌ์์ค๋ฅผ ํธ๋ฆฌํ๊ฒ ์กฐํ
04-7. ๋ค์ํ ์ค์ ํ์ ์ง์ - ์๋ฐ ์ฝ๋, XML
์คํ๋ง ์ปจํ ์ด๋๋ ๋ค์ํ ํ์์ ์ค์ ์ ๋ณด๋ฅผ ๋ฐ์๋ค์ผ ์ ์๊ฒ ์ ์ฐํ๊ฒ ์ค๊ณ๋์ด ์๋ค.
- ์๋ฐ์ฝ๋, XML, Groovy ๋ฑ๋ฑ
์ ๋ ธํ ์ด์ ๊ธฐ๋ฐ ์๋ฐ ์ฝ๋ ์ค์ ์ฌ์ฉ
์ง๊ธ๊น์ง ์ค์ตํ๋ ๋ฐฉ์์ด๋ค.
AnnotationConfigApplicationContext ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด์ ์๋ฐ ์ฝ๋๋ก ๋ ์ค์ ์ ๋ณด๋ฅผ ๋๊ธฐ๋ฉด ๋๋ค.
new AnnotationConfigApplicationContext(AppConfig.class);
XML ์ค์ ์ฌ์ฉ
์ต๊ทผ์๋ ์คํ๋ง ๋ถํธ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ฉด์ XML ๊ธฐ๋ฐ์ ์ค์ ์ ์ ์ฌ์ฉํ์ง ์๋๋ค.
ํ์ง๋ง ์์ง ๋ง์ ๋ ๊ฑฐ์ ํ๋ก์ ํธ๋ค์ด XML๋ก ๋์ด ์๊ณ , ๋ XML์ ์ฌ์ฉํ๋ฉด ์ปดํ์ผ ์์ด ๋น ์ค์ ์ ๋ณด๋ฅผ ๋ณ๊ฒฝํ ์ ์๋ ์ฅ์ ๋ ์์ผ๋ฏ๋ก ํ๋ฒ ๊ฐ๋จํ๊ฒ ๋ฐฐ์๋ณด๋๋ก ํ๊ฒ ๋ค.
GenericXmlApplicationContext๋ฅผ ์ฌ์ฉํ๋ฉด์ xml ์ค์ ํ์ผ์ ๋๊ธฐ๋ฉด ๋๋ค.
new GenericXmlApplicationContext("appConfig.xml");
ํ ์คํธ ํด๋์ค
test/java/hello/core/xml/XmlAppContext.java
package hello.core.xml;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
import static org.assertj.core.api.Assertions.*;
public class XmlAppContext {
@Test
void xmlAppContext() {
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
XML ๊ธฐ๋ฐ์ ์คํ๋ง ๋น ์ค์ ์ ๋ณด
main/resources/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">
<bean id="memberService" class="hello.core.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"></constructor-arg>
</bean>
<bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"></bean>
<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"></bean>
</beans>
(์ฐธ๊ณ ) ์คํ๋ง ๊ณต์ ๋ ํผ๋ฐ์ค ๋ฌธ์
https://spring.io/projects/spring-framework
Spring Framework
The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications - on any kind of deployment platform. A key element of Spring is infrastructural support at the application level: Spring focuse
spring.io
04-8. ์คํ๋ง ๋น ์ค์ ๋ฉํ ์ ๋ณด - BeanDefinition
์คํ๋ง์ด ๋ค์ํ ์ค์ ํ์์ ์ง์ํ ์ ์๋ ์ด์ ์ค ํ๋๋ BeanDefinition์ด๋ผ๋ ์ถ์ํ๋ค.
์ฝ๊ฒ ์ด์ผ๊ธฐํด์ ์ญํ ๊ณผ ๊ตฌํ์ ๊ฐ๋ ์ ์ผ๋ก ๋๋ ๊ฒ์ด๋ค.
์คํ๋ง ์ปจํ ์ด๋๋ ์ค์ ์ ๋ณด๊ฐ ์๋ฐ ์ฝ๋์ธ์ง XML์ธ์ง ๋ชฐ๋ผ๋ ๋๋ฉฐ ์ค์ง BeanDefinition๋ง ์๋ฉด ๋๋ค.
์ด๋ฌํ BeanDefinition์ ๋น ์ค์ ๋ฉํ์ ๋ณด๋ผ ํ๋ค.
@Bean, <bean> ๋น ๊ฐ๊ฐ ํ๋์ฉ ๋ฉํ์ ๋ณด๊ฐ ์์ฑ๋๋๋ฐ ์คํ๋ง ์ปจํ ์ด๋๋ ์ด ๋ฉํ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํ๋ง ๋น์ ์์ฑํ๋ค.
AnnotationConfigApplicationContext๋ AnnotatedBeanDefinitionReader๋ฅผ ์ฌ์ฉํด์ AppConfig.class๋ฅผ ์ฝ๊ณ BeanDefinition์ ์์ฑํ๋ค.
GenericXmlApplicationContext๋ XmlBeanDefinitionReader๋ฅผ ์ฌ์ฉํด์ appConfig.xml์ ์ฝ๊ณ BeanDefinition์ ์์ฑํ๋ค.
BeanDefinition ์ดํด๋ณด๊ธฐ
BeanDefinition ์ ๋ณด
- BeanClassName: ์์ฑํ ๋น์ ํด๋์ค ๋ช (์๋ฐ ์ฝ๋๋ก ์ค์ ํ ๊ฒฝ์ฐ ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฏ๋ก BeanClassName ์ ๋ณด๋ ์์)
- factoryBeanName: ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ด๋ฆ, ์) appConfig
- factoryMethodName: ๋น์ ์์ฑํ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ง์ , ์) memberService
- Scope: ์ฑ๊ธํค(๊ธฐ๋ณธ๊ฐ)
- lazyInit: ์คํ๋ง ์ปจํ
์ด๋๋ฅผ ์์ฑํ ๋ ๋ฐ๋ก ๋น์ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ค์ ๋น์ ์ฌ์ฉํ ๋๊น์ง ์ต๋ํ ์์ฑ์ ์ง์ฐ ์ฒ๋ฆฌํ๋์ง ์ฌ๋ถ
- InitMethodName: ๋น์ ์์ฑํ๊ณ , ์์กด๊ด๊ณ๋ฅผ ์ ์ฉํ ๋ค์ ํธ์ถ๋๋ ์ด๊ธฐํ ๋ฉ์๋ ๋ช
- DestroyMethodName: ๋น์ ์๋ช
์ฃผ๊ธฐ๊ฐ ๋๋์ ์ ๊ฑฐํ๊ธฐ ์ง์ ์ ํธ์ถ๋๋ ๋ฉ์๋ ๋ช
- Constructor arguments, Properties: ์์กด๊ด๊ณ ์ฃผ์
์์ ์ฌ์ฉํ๋ค. (์๋ฐ ์ฝ๋๋ก ์ค์ ํ ๊ฒฝ์ฐ ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฏ๋ก ํด๋น ์ ๋ณด๋ ์์)
ํ ์คํธ ํด๋์ค
test/java/hello/core/beandefinition/BeanDefinitionTest.java
package hello.core.beandefinition;
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 org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDefinitionTest {
@Test
@DisplayName("๋น ์ค์ ๋ฉํ์ ๋ณด ํ์ธ")
void findApplicationBean() {
// AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
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
);
}
}
}
}
์๋ฐ ์ฝ๋๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ ํ ์คํธ ๊ฒฐ๊ณผ
beanDefinitionName = appConfig, beanDefinitionGeneric bean: class [hello.core.AppConfig$$EnhancerBySpringCGLIB$$1ac4a1de]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
beanDefinitionName = memberService, beanDefinitionRoot bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionName = orderService, beanDefinitionRoot bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionName = memberRepository, beanDefinitionRoot bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionName = discountPolicy, beanDefinitionRoot bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=discountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
XML์ ์ฌ์ฉํ ๊ฒฝ์ฐ ํ ์คํธ ๊ฒฐ๊ณผ
beanDefinitionName = memberService, beanDefinitionGeneric bean: class [hello.core.member.MemberServiceImpl]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [appConfig.xml]
beanDefinitionName = memberRepository, beanDefinitionGeneric bean: class [hello.core.member.MemoryMemberRepository]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [appConfig.xml]
beanDefinitionName = orderService, beanDefinitionGeneric bean: class [hello.core.order.OrderServiceImpl]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [appConfig.xml]
beanDefinitionName = discountPolicy, beanDefinitionGeneric bean: class [hello.core.discount.RateDiscountPolicy]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [appConfig.xml]
'๐ฑ Spring > ์คํ๋ง ํต์ฌ ์๋ฆฌ - ๊ธฐ๋ณธํธ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ธ๋ก๊ทธ์ ์ ๋ณด
Claire's Study Note
Hi.Claire