Spring Bean
Spring Bean μ΄λ IoC Container λ΄λΆμ λ€μ΄μλ κ°μ²΄λ‘ νμν λ κΊΌλ΄μ μ¬μ©ν μ μλ€.
@Bean
μ΄λ xml
μ€μ μ ν΅ν΄ μΌλ° κ°μ²΄λ₯Ό Bean μΌλ‘ λ±λ‘ν μ μλ€.
μ€νλ§μ μ€νλ§ μ»¨ν
μ΄λμ μ€νλ§ λΉμ λ±λ‘ν λ, κΈ°λ³ΈμΌλ‘ μ±κΈν€μΌλ‘ λ±λ‘νλ€. λ°λΌμ κ°μ μ€νλ§ λΉμ΄λ©΄ λͺ¨λ κ°μ μΈμ€ν΄μ€λ€.
Spring Bean μμ± κ³Όμ
Spring Bean μ μλͺ μ£ΌκΈ°
- κ°μ²΄ μμ±
- μμ‘΄ μ€μ
- μ΄κΈ°ν
- μ¬μ©
- μλ©Έ
Bean μ IoC Container μ μν΄ μλͺ
μ£ΌκΈ°λ₯Ό κ΄λ¦¬νλ©° μ΄κΈ°ν λ°©λ²μ @PostConstruct
λ₯Ό Bean μλ©Έμμλ @PreDestroy
λ₯Ό μ¬μ©νλ€.
μμ±ν Bean μ λ±λ‘ν λλ @ComponentScan
μ μ΄μ©νκ±°λ @Configuration
μ @Bean
μ μ¬μ©νμ¬ Bean μ€μ νμΌμ μ§μ Bean μ λ±λ‘ν μ μλ€.
Bean λ±λ‘ λ°©λ²
@Component
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
Bean μΌλ‘ λ±λ‘νκ³ μ νλ ν΄λμ€ μ μΈλΆ μλ¨μ @Component
μ λν
μ΄μ
μ μΆκ°νμ¬ Bean μΌλ‘ λ±λ‘ν μ μλ€.
μμ£Ό μ¬μ©λλ @Controller
@Service
@Repository
μ λν
μ΄μ
μ λͺ¨λ @Component
μ λν
μ΄μ
μ΄ ν¬ν¨λμ΄ μλ€.
μ€νλ§μ @ComponentScan
μ ν΅ν΄ @Component
μ λν
μ΄μ
μ΄ μ μΈλ λͺ¨λ ν΄λμ€λ₯Ό μλμΌλ‘ μ€μΊν λ€ Singleton Bean μΌλ‘ λ±λ‘νλ€.
@Bean
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
μ€μ ν΄λμ€λ‘ μ¬μ©ν ν΄λμ€λ₯Ό μμ±νκ³ μ μΈλΆ μλ¨μ @Configuration
μ λν
μ΄μ
μ μΆκ°νμ¬ Bean μ€μ μ μν ν΄λμ€μμ λͺ
μνλ€.
Bean μΌλ‘ λ±λ‘ν ν΄λμ€λ₯Ό λ°ννλ λ©μλλ₯Ό λ§λ€κ³ ν΄λΉ λ©μλ μλ¨μ @Bean
μ λν
μ΄μ
μ μΆκ°νμ¬ Singleton Bean μ λ±λ‘ν μ μλ€.
μ΄ λ μμ±λλ Bean μ μ΄λ¦μ κΈ°λ³Έμ μΌλ‘ λ©μλλͺ
μΌλ‘ μ§μ λλ©°, @Bean(name = "name")
μ ν΅ν΄ μ§μ μ΄λ¦μ μ§μ ν΄μ€ μ λ μλ€.
Bean Scope
Bean Scope λ Bean μ΄ μ‘΄μ¬ν μ μλ λ²μλ₯Ό λ»νλ©° Singleton
Prototype
Request
Session
Application
λ±μ΄ μ‘΄μ¬νλ€.
Singleton
- Singleton μ κΈ°λ³Έ Scope λ‘ IoC 컨ν μ΄λμ μμκ³Ό μ’ λ£κΉμ§ μ μ§λλ κ°μ₯ λμ λ²μμ Scope λ€.
Prototype
- Prototype μ Bean μ μμ±κ³Ό μμ‘΄κ΄κ³ μ£Όμ κΉμ§λ§ κ΄μ¬νκ³ λλ κ΄λ¦¬νμ§ μλ λ§€μ° μ§§μ λ²μμ Scope λ€.
Request
- Request λ μΉ μμ²μ΄ λ€μ΄μ€κ³ λκ°λ κΉμ§ μ μ§νλ Scope λ€.
Session
- Session μ μΉ μΈμ μμ±λΆν° μ’ λ£κΉμ§ μ μ§νλ Scope λ€.
Application
- Application μ WebServletContext μ κ°μ λ²μλ‘ μ μ§νλ Scope λ€.
IoC
Inversion of Control, IoC λ μ μ΄μ μμ μΌλ‘ νλ‘κ·Έλ¨μ νλ¦μ μ§μ μ μ΄νλ κ²μ΄ μλ μΈλΆμμ κ΄λ¦¬νλ κ²μ΄λ€. μ¦, μ½λμ μ΅μ’ νΈμΆμ κ°λ°μκ° μ μ΄νλ κ²μ΄ μλ νλ μμν¬ λ΄λΆμμ κ²°μ λ λλ‘ μ΄λ£¨μ΄μ§λ κ²μ μλ―Ένλ€. κ°μ²΄μ μμ‘΄μ±μ μμ μν€λ©΄ κ°μ²΄ κ°μ κ²°ν©λλ₯Ό μ€μ΄κ³ μ μ°ν μ½λλ₯Ό μμ±ν μ μμ΄ κ°λ μ± λ° μ μ§ λ³΄μκ° νΈν΄μ§λ€λ μ₯μ μ΄ μλ€. μ€νλ§μ λͺ¨λ κ°μ²΄λ₯Ό μ€νλ§μ΄ μ€νλ λ λ§λ€μ΄λκ³ νμν κ³³μ μ£Όμ μμΌ νΉμ κ°μ²΄λ₯Ό μμ‘΄νλ κ°μ²΄μμ μμ‘΄ κ°μ²΄λ₯Ό μ¬μ©ν μ μλλ‘ νλ€.
IoC μ’ λ₯
DL
μ μ₯μμ μ μ₯λμ΄ μλ Bean μ μ κ·ΌνκΈ° μν΄ μ»¨ν μ΄λκ° μ 곡νλ API λ₯Ό ν΅ν΄ Bean μ Lookup νλ κ²μ΄λ€. DL μ 컨ν μ΄λ μ’ μμ΄ μ¦κ°νκΈ° λλ¬Έμ μ£Όλ‘ DI λ₯Ό μ¬μ©νλ€.
DI
λΉ μ€μ μ 보λ₯Ό λ°νμΌλ‘ κ° ν΄λμ€κ°μ μμ‘΄κ΄κ³λ₯Ό 컨ν μ΄λκ° μλμΌλ‘ μ°κ²°ν΄μ€λ€.
IoC Container
μΈμ€ν΄μ€ μμ±λΆν° μλ©ΈκΉμ§ μΈμ€ν΄μ€μ μλͺ μ£ΌκΈ°λ₯Ό κ΄λ¦¬ν΄μ£ΌκΈ° λλ¬Έμ κ°λ°μλ λΉμ¦λμ€ λ‘μ§μλ§ μ§μ€ν μ μλ€.
- κ°μ²΄μ μμ±μ μ± μμ§κ³ μμ‘΄μ±μ κ΄λ¦¬
- POJO μ μμ±, μ΄κΈ°ν, μλΉμ€, μλ©Έμ λν κΆλμ κ°μ§
- κ°λ°μλ€μ΄ μ§μ POJO λ₯Ό μμ±ν μ μμ§λ§ 컨ν μ΄λμκ² λ§‘κΉ
IoC Container μ μν
ApplicationContext λ IoC Container μ΄λ©° Bean μ μΈμ€ν΄μ€ννκ³ κ΅¬μ±νκ³ μ‘°λ¦½νλ μν μ νλ€. μ ν리μΌμ΄μ μ€ν μμ μ Bean μ€λΈμ νΈλ₯Ό μΈμ€ν΄μ€ννκ³ DI ν λ€ μ΅μ΄λ‘ μ ν리μΌμ΄μ μ κ°λν Bean νλλ₯Ό μ 곡νλ€.
IoC Container μ μ’ λ₯
ApplicationContext λ BeanFactory μ μλΈ μΈν°νμ΄μ€
BeanFactory
- 컨ν μ΄λμμ Bean μ μμ±νκ³ DI νλ κΈ°λ₯μ μ 곡
- Bean λ±λ‘, μμ±, μ‘°ν, λ°νμ κ΄λ¦¬
- ν©ν 리 λμμΈ ν¨ν΄μ ꡬνν κ²μΌλ‘ λΉμ μμ±νκ³ λΆλ°°νλ μ± μμ κ°μ§
- Bean μ μ‘°νν μ μλ getBean() λ©μλκ° μ μλμ΄ μμ
ApplicationContext
- BeanFactory μ κΈ°λ₯μ λν΄ μ€νλ§μ κ°μ’ λΆκ° κΈ°λ₯μ μΆκ°λ‘ μ 곡
- κ΅μ νκ° μ§μλλ ν μ€νΈ λ©μμ§λ₯Ό κ΄λ¦¬
- μ΄λ―Έμ§κ°μ νμΌ μμμ λ‘λν μ μλ ν¬κ΄μ μΈ λ°©λ² μ 곡
- 리μ€λλ‘ λ±λ‘λ λΉμκ² μ΄λ²€νΈ λ°μμ μλ €μ€
μ€νλ§ μ»¨ν μ΄λ μμ±
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
ApplicationContext
λ₯Ό μ€νλ§ μ»¨ν μ΄λλΌκ³ νλ€.ApplicationContext
λ μΈν°νμ΄μ€μ΄λ€.- μ€νλ§ μ»¨ν μ΄λλ XML κΈ°λ°μΌλ‘ λ§λ€ μ μκ³ , μ΄λ Έν μ΄μ κΈ°λ°μ Java μ€μ ν΄λμ€λ‘ λ§λ€ μ μλ€.
- AppConfig λ₯Ό μ¬μ©ν λ°©μμ΄ μ΄λ Έν μ΄μ κΈ°λ°μ Java μ€μ ν΄λμ€λ‘ μ€νλ§ μ»¨ν μ΄λλ₯Ό λ§λ κ²μ΄λ€.
컨ν μ΄λμ λ±λ‘λ λͺ¨λ λΉ μ‘°ν
@Test
@DisplayName("λͺ¨λ λΉ μΆλ ₯")
void findAllBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object = " + bean);
}
}
@Test
@DisplayName("μ ν리μΌμ΄μ
λΉ μΆλ ₯")
void findApplicationBean() {
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);
}
}
}
μ€νλ§ λΉ μ‘°ν - κΈ°λ³Έ
- Spring Container μμ Spring Bean μ μ°Ύλ κ°μ₯ κΈ°λ³Έμ μΈ μ‘°ν λ°©λ²
ac.getBean(λΉμ΄λ¦, νμ );
ac.getBean(νμ );
- μ‘°ν λμμΈ Spring Bean μ΄ μμΌλ©΄
NoSuchBeanDefinitionException
λ°μ
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 findBeanByExactType() {
MemberServiceImpl memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("μλ λΉ μ΄λ¦μΌλ‘ μ‘°ν")
void findNotExistingBeanByName() {
assertThatThrownBy(() -> ac.getBean("xxxx", MemberService.class))
.isInstanceOf(NoSuchBeanDefinitionException.class);
}
μ€νλ§ λΉ μ‘°ν - λμΌν νμ μ΄ λ μ΄μ
- νμ μΌλ‘ μ‘°ν μ κ°μ νμ μ μ€νλ§ λΉμ΄ λ μ΄μμ΄λ©΄ μ€λ₯κ° λ°μνλ€. μ΄λλ λΉ μ΄λ¦μ μ§μ .
ac.getBeansOfType()
μ μ¬μ©νλ©΄ ν΄λΉ νμ μ λͺ¨λ λΉμ μ‘°νν μ μλ€.
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("νμ
μΌλ‘ μ‘°ν μ λμΌν νμ
μ΄ λ μ΄μ μμΌλ©΄ μμΈ λ°μ")
void findBeanByTypeDuplicate() {
assertThatThrownBy(() -> ac.getBean(MemberRepository.class))
.isInstanceOf(NoUniqueBeanDefinitionException.class);
}
@Test
@DisplayName("νμ
μΌλ‘ μ‘°ν μ λμΌν νμ
μ΄ λ μ΄μ μμΌλ©΄ λΉ μ΄λ¦ μ§μ ")
void findBeanByName() {
MemberRepository memberRepository = ac.getBean("memberRepository", 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 memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
μ€νλ§ λΉ μ‘°ν - μμ κ΄κ³
- λΆλͺ¨ νμ μΌλ‘ μ‘°ννλ©΄, μμ νμ λ ν¨κ» μ‘°ννλ€.
- κ·Έλμ λͺ¨λ μλ° κ°μ²΄μ μ΅κ³ λΆλͺ¨μΈ
Object
νμ μΌλ‘ μ‘°ννλ©΄ λͺ¨λ μ€νλ§ λΉμ μ‘°ννλ€.
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("λΆλͺ¨ νμ
μΌλ‘ μ‘°ν μ μμμ΄ λ μ΄μ μμΌλ©΄ μμΈ λ°μ")
void findBeanByParentTypeDuplicate() {
assertThatThrownBy(() -> ac.getBean(DiscountPolicy.class))
.isInstanceOf(NoUniqueBeanDefinitionException.class);
}
@Test
@DisplayName("λΆλͺ¨ νμ
μΌλ‘ μ‘°ν μ μμμ΄ λ μ΄μ μμΌλ©΄ λΉ μ΄λ¦ μ§μ ")
void findBeanByParentTypeBeanName() {
DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
@Test
@DisplayName("νΉμ νμ νμ
μΌλ‘ μ‘°ν")
void findBeanBySubType() {
DiscountPolicy rateDiscountPolicy = ac.getBean(RateDiscountPolicy.class);
assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
@Test
@DisplayName("λΆλͺ¨ νμ
μΌλ‘ λͺ¨λ μ‘°ν")
void findAllByParentType() {
Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
assertThat(beansOfType.size()).isEqualTo(2);
}
@Test
@DisplayName("λΆλͺ¨ νμ
μΌλ‘ λͺ¨λ μ‘°ν - Object")
void findAllByObjectType() {
Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
}
@Configuration
static class TestConfig {
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
}
}
BeanFactory μ ApplicationContext
BeanFactory
- μ€νλ§ μ»¨ν μ΄λμ μ΅μμ μΈν°νμ΄μ€
- μ€νλ§ λΉμ κ΄λ¦¬νκ³ μ‘°ννλ μν μ λ΄λΉ
getBean()
μ μ 곡
ApplicationContext
BeanFactory
μ κΈ°λ₯μ λͺ¨λ μμλ°μμ μ 곡- μ ν리μΌμ΄μ
κ°λ°ν λλ
BeanFactory
μμ μ 곡νλ κΈ°λ₯ μΈμλ λ§μ λΆκ°κΈ°λ₯μ΄ νμ
ApplicationContext κ° μ 곡νλ λΆκ°κΈ°λ₯
- λ©μμ§μμ€λ₯Ό νμ©ν κ΅μ ν κΈ°λ₯
- νκ΅μμ λ€μ΄μ€λ©΄ νκ΅μ΄, μμ΄κΆμμ λ€μ΄μ€λ©΄ μμ΄λ‘ μΆλ ₯
- νκ²½λ³μ
- λ‘컬, κ°λ°, μ΄μλ±μ ꡬλΆν΄μ μ²λ¦¬
- μ ν리μΌμ΄μ
μ΄λ²€νΈ
- μ΄λ²€νΈλ₯Ό λ°ννκ³ κ΅¬λ νλ λͺ¨λΈμ νΈλ¦¬νκ² μ§μ
- νΈλ¦¬ν 리μμ€ μ‘°ν
- νμΌ, ν΄λμ€ν¨μ€, μΈλΆ λ±μμ 리μμ€λ₯Ό νΈλ¦¬νκ² μ‘°ν
μ 리
- ApplicationContext λ BeanFactory μ κΈ°λ₯μ μμλ°λλ€.
- ApplicationContext λ λΉ κ΄λ¦¬ κΈ°λ₯ + νΈλ¦¬ν λΆκ° κΈ°λ₯μ μ 곡νλ€.
- BeanFactory λ₯Ό μ§μ μ¬μ©ν μΌμ κ±°μ μκ³ , ApplicationContext λ₯Ό μ¬μ©νλ€.
- BeanFactory λ ApplicationContext λ₯Ό λͺ¨λ μ€νλ§ μ»¨ν μ΄λλΌκ³ νλ€.
μ€νλ§ λΉ μ€μ λ©ν μ 보 - BeanDefinition
- μ€νλ§μ μ΄λ»κ² μ΄λ° λ€μν μ€μ νμμ μ§μνλκ°?
- κ·Έ μ€μ¬μλ BeanDefinition μ΄λΌλ μΆμνκ° μλ€.
- XML, μλ° μ½λ λ±μ΄ BeanDefinition μΌλ‘ λ§λ€μ΄μ§λ©΄ μ€νλ§ μ»¨ν μ΄λλ BeanDefinition λ§ μλ©΄λλ€.
BeanDefinition
μ λ©νμ λ³΄λΌ νλ€.@Bean
<bean>
λΉ κ°κ° νλμ© λ©ν μ λ³΄κ° μμ±λλ€.
- μ€νλ§ μ»¨ν
μ΄λλ μ΄ λ©νμ 보λ₯Ό κΈ°λ°μΌλ‘ μ€νλ§ λΉμ μμ±νλ€.
AnnotationConfigApplicationContext
λAnnotatedBeanDefinitionReader
λ₯Ό μ¬μ©ν΄μAppConfig.class
λ₯Ό μ½κ³BeanDefinition
μ μμ±νλ€.
BeanDefinition
BeanClassName
factoryBeanName
factoryMethodName
Scope
lazyInit
InitMethodName
DestroyMethodName
Constructor arguments, Properties
μ 리
- BeanDefinition μ μ§μ μμ±ν΄μ μ€νλ§ μ»¨ν μ΄λμ λ±λ‘ν μ λ μλ€.
- νμ§λ§ μ€λ¬΄μμ BeanDefinition μ μ§μ μ μνκ±°λ μ¬μ©ν μΌμ κ±°μ μλ€.
- BeanDefinition μ λν΄μ λ무 κΉμ΄μκ² μ΄ν΄νκΈ° 보λ¨, μ€νλ§μ΄ λ€μν ννμ μ€μ μ 보λ₯Ό BeanDefinition μΌλ‘ μΆμνν΄μ μ¬μ©νλ€λ κ² μ λλ§ μ΄ν΄νλ©΄ λλ€.
- κ°λ μ€νλ§ μ½λλ μ€νλ§ κ΄λ ¨ μ€ν μμ€μ μ½λλ₯Ό λ³Ό λ, BeanDefinition μ΄λΌλ κ²μ΄ λ³΄μΌ λκ° μλλ°, μ΄λ μ΄λ° λ©μ»€λμ¦μ λ μ¬λ¦¬λ©΄ λλ€.