IoC๋ Inversion of Control์ ์ฝ์๋ก ์ ์ด์ ์ญ์ ์ด๋ผ๋ ์๋ฏธ์ด๋ค. ์ ์ด์ ์ญ์ ์ด๋ ํ๋ก๊ทธ๋จ์ ์ ์ด ํ๋ฆ ๊ตฌ์กฐ๊ฐ ๋ค๋ฐ๋๋ ๊ฒ์ด๋ผ ์ค๋ช
ํ ์ ์๋ค. IoC์์๋ ์ค๋ธ์ ํธ๊ฐ ์์ ์ด ์ฌ์ฉํ ์ค๋ธ์ ํธ๋ฅผ ์ค์ค๋ก ์ ํํ๊ฑฐ๋ ์์ฑํ์ง ์๋๋ค. ๋ํ, ์์ ๋ ์ด๋ป๊ฒ ๋ง๋ค์ด์ง๊ณ ์ด๋์ ์ฌ์ฉ๋๋์ง๋ฅผ ์ ์ ์๋ค. ๋ชจ๋ ์ ์ด ๊ถํ์ ์์ ์ด ์๋ ๋ค๋ฅธ ๋์์๊ฒ ์์ํ๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ธ๋ฆฟ๋ ์ ์ด์ ์ญ์ ๊ฐ๋
์ด ์ ์ฉ๋์ด์๋ค๊ณ ๋ณผ ์ ์๋ค. ์ผ๋ฐ์ ์ผ๋ก๋ main()
๋ฉ์๋์์ ์์ํด ๊ฐ๋ฐ์๊ฐ ๋ฏธ๋ฆฌ ์ ํ ์์๋ฅผ ๋ฐ๋ผ ์ค๋ธ์ ํธ๊ฐ ์์ฑ๋๊ณ ์คํ๋๋ค. ํ์ง๋ง ์๋ธ๋ฆฟ์ ์คํ์ ๊ฐ๋ฐ์๊ฐ ์ง์ ์ ์ดํ ์ ์๋ ๋ฐฉ๋ฒ์ ์๋ค. ๋์ ์๋ธ๋ฆฟ์ ๋ํ ์ ์ด ๊ถํ์ ๊ฐ์ง ์ปจํ
์ด๋๊ฐ ์ ์ ํ ์์ ์ ์๋ธ๋ฆฟ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค๊ณ ๊ทธ ์์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
ํ๋ ์์ํฌ๋ ์ ์ด์ ์ญ์ ๊ฐ๋
์ด ์ ์ฉ๋ ๋ํ ๊ธฐ์ ์ด๋ค. ํ๋ ์์ํฌ๋ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๊ฐ ํ๋ ์์ํฌ์ ์ํด ์ฌ์ฉ๋๋ค. ํ๋ ์์ํฌ๊ฐ ํ๋ฆ์ ์ฃผ๋ํ๋ ์ค์ ๊ฐ๋ฐ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ฝ๋๋ฅผ ์ฌ์ฉํ๋๋ก ๋ง๋ ๊ตฌ์กฐ์ด๋ค.
ํ๋ ์์ํฌ vs ๋ผ์ด๋ธ๋ฌ๋ฆฌ
ํ๋ ์์ํฌ๊ฐ ๋ด๊ฐ ์์ฑํ ์ฝ๋๋ฅผ ์ ์ดํ๊ณ , ์คํ์ํ๋ฉด ๊ทธ๊ฒ์ ํ๋ ์์ํฌ์ด๋ค.(ex. Junit)
๋ด๊ฐ ์์ฑํ ์ฝ๋๊ฐ ์ง์ ์ ์ด์ ํ๋ฆ์ ๋ด๋นํ๋ค๋ฉด ๊ทธ๊ฒ์ ํ๋ ์์ํฌ๊ฐ ์๋๋ผ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค. (ex. Java to Xml)
Spring์ IoC ์ฉ์ด
bean : ์คํ๋ง์ด IoC ๋ฐฉ์์ผ๋ก ๊ด๋ฆฌํ๋ ์ค๋ธ์ ํธ or ๊ด๋ฆฌ๋๋ ์ค๋ธ์ ํธ์ด๋ค.
( ์คํ๋ง์ด ์ง์ ๊ทธ ์์ฑ๊ณผ ์ ์ด๋ฅผ ๋ด๋นํ๋ ์ค๋ธ์ ํธ๋ง์ ๋น์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. )
bean factory : ์คํ๋ง์ IoC๋ฅผ ๋ด๋นํ๋ ํต์ฌ ์ปจํ
์ด๋๋ก ๋น์ ๋ฑ๋ก, ์์ฑ, ์กฐํ, ๋ฐํ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ๋ด๋นํ๋ค. ๋ณดํต ๋น ํฉํ ๋ฆฌ๋ฅผ ํ์ฅํ Application Context๋ฅผ ์ฌ์ฉํ๋ค.
application context : bean factory๋ฅผ ํ์ฅํ IoC ์ปจํ
์ด๋๋ค. bean factory์ ์ถ๊ฐ๋ก ์คํ๋ง์ด ์ ๊ณตํ๋ ๊ฐ์ข
๋ถ๊ฐ ์๋น์ค๋ฅผ ์ถ๊ฐํ๋ค. ์ฆ, ์ ํ๋ฆฌ์ผ์ด์
์ง์ ๊ธฐ๋ฅ์ ๋ชจ๋ ํฌํจํด์ ์ด์ผ๊ธฐํ๋ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด๋๋ค.
Configuration metadata(์ค์ /์ค์ ๋ฉํ ์ ๋ณด) : application context ๋๋ bean factory๊ฐ IoC๋ฅผ ์ ์ฉํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฉํ์ ๋ณด๋ฅผ ๋งํ๋ค. ๋ณดํต IoC ์ปจํ
์ด๋์ ์ํด ๊ด๋ฆฌ๋๋ ์ ํ๋ฆฌ์ผ์ด์
์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๊ณ ๊ตฌ์ฑํ ๋ ์ฌ์ฉ
@Configuration
์ด๋
ธํ
์ด์
์ผ๋ก ์ค์
IoC container(DI container) : IoC๋ฐฉ์์ผ๋ก ๋น์ ๊ด๋ฆฌํ๋ค๋ ๋ป์์ application context๋ bean factory๋ฅผ ๊ทธ๋ ๊ฒ ๋ถ๋ฅธ๋ค. IoC container๋ ๋น ํฉํ ๋ฆฌ ๊ด์ ์์ ์ด์ผ๊ธฐ ํ๋ ๊ฒ์ด๋ฉฐ, ๊ทธ๋ฅ ์ปจํ
์ด๋ ํน์ ์คํ๋ง ์ปจํ
์ด๋๋ผ๊ณ ํ ๋๋ application context๋ฅผ ๊ฐ๋ฆฌํค๋ ๊ฒ์ด๋ผ๊ณ ๋ณด๋ฉด๋๋ค.
spring framework : IoC container, application context๋ฅผ ํฌํจํด์ ์คํ๋ง์ด ์ ๊ณตํ๋ ๋ชจ๋ ๊ธฐ๋ฅ์ ํตํ์ด ๋งํ ๋ ์ฃผ๋ก ์ฌ์ฉ
Factory๋ ๊ฐ์ฒด์ ์์ฑ ๋ฐฉ๋ฒ์ ๊ฒฐ์ ํ๊ณ ๊ทธ๋ ๊ฒ ๋ง๋ค์ด์ง Object๋ฅผ ๋๋ ค์ฃผ๋ ์ญํ ์ ํ๋ ํด๋์ค์ด๋ค. Factory๋ ๋จ์ง ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๋ ์ชฝ๊ณผ ์์ฑ๋ ์ค๋ธ์ ํธ๋ฅผ ์ฌ์ฉํ๋ ์ชฝ์ ์ญํ ๊ณผ ์ฑ
์์ ๊น๋ํ๊ฒ ๋ถ๋ฆฌํ๋ ค๋ ๋ชฉ์ ์ผ๋ก ์ฌ์ฉํ๋ ๊ฒ์ด๋ค.
package springbook.user.dao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class DaoFactory {
@Bean
public UserDao userDao() {
UserDao dao = new UserDao(connectionMaker());
return dao;
}
@Bean
public ConnectionMaker connectionMaker() {
ConnectionMaker connectionMaker = new DConnectionMaker();
return connectionMaker;
}
}
@Configuration
: applicatoin context ๋๋ bean factory๊ฐ ์ฌ์ฉํ ์ค์ ์ ๋ณด๋ผ๋ ์ด๋
ธํ
์ด์
@Bean
: ์ค๋ธ์ ํธ ์์ฑ์ ๋ด๋นํ๋ IoC์ฉ ๋ฉ์๋๋ผ๋ ํ์
import java.sql.SQLException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.ApplicationContext;
import springbook.user.domain.User;
public class UserDaoTest {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// applicationContext๋ ์คํ๋ง ์ปจํ
์ด๋์ด๋ฉฐ, ์ธํฐํ์ด์ค๋ค.(๋คํ์ฑ)
// AnnotationConfigApplicationContext์ ๊ตฌํ
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(DaoFactory.class);
UserDao dao = context.getBean("userDao", UserDao.class);
User user = new User();
user.setId("testId");
user.setName("testName");
user.setPassword("testtest");
dao.add(user);
}
}
AnnotationConfigApplicationContext
๋ @Configuration
(์ด๋
ธํ
์ด์
๊ธฐ๋ฐ) ์ด ๋ถ์ ์๋ฐ ์ฝ๋๋ฅผ ์ค์ ์ ๋ณด๋ก ์ฌ์ฉํ ๋ ์ฌ์ฉํ๋ฉด๋๋ค.
ApplicationContext๋ DaoFactory ํด๋์ค๋ฅผ ์ค์ ์ ๋ณด๋ก ๋ฑ๋กํด๋๊ณ @Bean
์ด ๋ถ์ ๋ฉ์๋ ์ด๋ฆ์ ๊ฐ์ ธ์ ๋น ๋ชฉ๋ก์ ๋ง๋ค์ด ๋๋ค.
ํด๋ผ์ด์ธํธ๊ฐ ApplicationContext๋ฅผ getBean()๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด ์์ ์ ๋น ๋ชฉ๋ก์์ ์์ฒญํ ์ด๋ฆ์ด ์๋ค๋ฉด ๋น์ ์์ฑํ๋ ๋ฉ์๋๋ฅผ ํธ์ถํด ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ ํ ๋ฐํํ๋ค.
ApplicationContext๋ ๋ํ ์ฑ๊ธํค์ ์ ์ฅํ๊ณ ๊ด๋ฆฌํ๋ Singleton Registry์ด๊ธฐ๋ ํ๋ค. ์คํ๋ง์ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณ๋ค๋ฅธ ์ค์ ์ ํ์ง ์์ผ๋ฉด ๋ด๋ถ์์ ์์ฑํ๋ ๋น ์ค๋ธ์ ํธ๋ฅผ ๋ชจ๋ ์ฑ๊ธํค์ผ๋ก ๋ง๋ ๋ค.
์คํ๋ง์ ์๋ฒ ํ๊ฒฝ์์ ์ฑ๊ธํค์ด ๋ง๋ค์ด์ ธ ์๋น์ค ์ค๋ธ์ ํธ ๋ฐฉ์์ผ๋ก ์ฌ์ฉ๋๋ ๊ฒ์ ์ ๊ทน ์ง์งํ๋ค. ํ์ง๋ง ์๋ฐ์ ๊ธฐ๋ณธ์ ์ธ ์ฑ๊ธํค ํจํด์ ๊ตฌํ ๋ฐฉ์์ ์ฌ๋ฌ๊ฐ์ง ๋จ์ ์ด ์๊ธฐ๋๋ฌธ์ ์คํ๋ง์ ์ง์ ์ฑ๊ธํค ํํ์ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค๊ณ ๊ด๋ฆฌํ๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
Singleton Registry์ ์ฅ์ ์ ํ๋ฒํ ์๋ฐ ํด๋์ค์ด๋๋ผ๋ IoC๋ฐฉ์์ ์ปจํ
์ด๋๋ฅผ ์ฌ์ฉํด ์์ฑ๊ณผ ๊ด๊ณ์ค์ , ์ฌ์ฉ ๋ฑ์ ๋ํ ์ ์ด๊ถ์ ์์ฝ๊ฒ ์ฑ๊ธํค ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ ธ ๊ด๋ฆฌ๋๊ฒ ํ ์ ์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ํ
์คํธ ํ๊ฒฝ์์๋ ์์ ๋กญ๊ฒ ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค ์ ์๊ณ , ํ
์คํธ๋ฅผ ์ํ ๋ชฉ์ ์ผ๋ก ์ค๋ธ์ ํธ๋ฅผ ๋์ฒดํ๋ ๊ฒ๋ ๊ฐ๋จํ๋ค.
์ฑ๊ธํค์ด ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์ ์๋น์ค ํํ์ ์ค๋ธ์ ํธ๋ก ์ฌ์ฉ๋๋ ๊ฒฝ์ฐ์๋ stateless ๋ฐฉ์์ผ๋ก ๋ง๋ค์ด์ ธ์ผํ๋ค. ์ด๋๋ ์ฝ๊ธฐ์ ์ฉ ๊ฐ์ด๋ผ๋ฉด ์ด๊ธฐํ ์์ ์ ์ธ์คํด์ค ๋ณ์์ ์ ์ฅํด๋๊ณ ๊ณต์ ํ๋ ๊ฒ์ ๋ฌธ์ ์๋ค. ๋ง์ฝ ๊ฐ ์์ฒญ์ ๋ํ ์ ๋ณด๋, DB ์๋ฒ์ ๋ฆฌ์์ค๋ก ๋ถํฐ ์์ฑํ ์ ๋ณด๋ ํ๋ผ๋ฏธํฐ์ ๋ก์ปฌ ๋ณ์, ๋ฆฌํด ๊ฐ์ ์ด์ฉํ๋ฉด ๋๋ค. ๋ฉ์๋ ํ๋ผ๋ฏธํฐ๋, ๋ฉ์๋ ์์์ ์์ฑ๋๋ ๋ก์ปฌ ๋ณ์๋ ๋งค๋ฒ ์๋ก์ด ๊ฐ์ ์ ์ฅํ ๋
๋ฆฝ์ ์ธ ๊ณต๊ฐ์ด ๋ง๋ค์ด์ง๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค์ด๋ผ๊ณ ํด๋ ๋ฌธ์ ์๋ค.
๋ฑ๋ก๋ ๋น ํ์ธํ๊ธฐ
์ค์ ๋ก ๊ฐ๋ฐ์ ์๋ ํ
์คํธ ์ฝ๋๋ ์ฌ์ฉํ ์ํฉ์ ๊ฑฐ์ ์์ผ๋ ์๋ ๋๊ฐ์ง ๊ฒฝ์ฐ์ ๋๋นํด ์์๋๋ ๊ฒ์ด ์ข๋ค.
์์ํ ์๋ฐ ์ ํ๋ฆฌ์ผ์ด์
์์ ์คํ๋ง ์ปจํ
์คํธ๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉํด์ผํ๋ ๊ฒฝ์ฐ
์๋ ์์กด ๊ด๊ณ ์ฃผ์
์ ์ดํด๋ฅผ ์ํด
๋ชจ๋ ๋น ๊ฐ์ ธ์ค๊ธฐ
package dh0023.springcore.beanfind;
import dh0023.springcore.config.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;
class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@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);
// BeanDefinition.ROLE_APPLICATION : ์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ๊ธฐ์ํด ์ง์ ๋ฑ๋กํ ๋น๋ค(or ์ธ๋ถ ๋ผ์ด๋ธ๋ด)
// BeanDefinition.ROLE_INFRASTRUCTURE : ์คํ๋ง ๋ด๋ถ์์ ์ฌ์ฉํ๋ ๋น
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + " object = " + bean);
}
}
}
}
๋น ์ด๋ฆ / ๋น ํ์
์ผ๋ก ์กฐํ
package dh0023.springcore.beanfind;
import dh0023.springcore.config.AppConfig;
import dh0023.springcore.member.service.MemberService;
import dh0023.springcore.member.service.MemberServiceImpl;
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() {
// ์ญํ ๊ณผ ๊ตฌํ์ ๊ตฌ๋ถํ๊ณ , ์ญํ ์ ์์กดํด์ผํ๋ค.
// ํ์ง๋ง ๊ตฌ์ฒด ํ์
์ผ๋ก ์กฐํํ๋๊ฑด ๊ตฌํ์ ์์กดํ๋ ๊ฒ์ด๋ฏ๋ก ์ข์ ๋ฐฉ์์ ์๋๋ค.
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("๋น ์ด๋ฆ์ผ๋ก ์กฐํX")
void findBeanByNameX() {
// ac.getBean("xxxxx", MemberService.class);
// org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'xxxxx' available
// lambda ์คํํ ์ผ์ชฝ Exception์ด ์ํ๋์ด์ผํ๋ค.
assertThrows(NoSuchBeanDefinitionException.class, () -> ac.getBean("xxxxx", MemberService.class));
}
}
๊ฐ์ ํ์
์ด ๋ ์ด์์ธ ๊ฒฝ์ฐ ์กฐํ
package dh0023.springcore.beanfind;
import dh0023.springcore.member.repository.MemberRepository;
import dh0023.springcore.member.repository.MemoryMemberRepository;
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.*;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("ํ์
์ผ๋ก ์กฐํ์ ๊ฐ์ ํ์
์ด ๋ ์ด์ ์์ผ๋ฉด, ์ค๋ณต ์ค๋ฅ ๋ฐ์")
void findBeanByTypeDuplicate() {
// org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'dh0023.springcore.member.repository.MemberRepository' available: expected single matching bean but found 2: memberRepository,memberRepository2
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(MemberRepository.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);
}
/**
* ApplicationContextSameBeanFindTest์์์๋ง ํ
์คํธ ์ฉ๋๋ก ์ฌ์ฉํ Class
*/
@Configuration
static class SameBeanConfig {
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2() {
return new MemoryMemberRepository();
}
}
}
์์ ๊ด๊ณ
๋ถ๋ชจ ํ์
์ผ๋ก ์คํ๋ง ๋น ์กฐํ์, ์์ ํ์
๋ ํจ๊ป ์กฐํํ๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์๋ฐ ๊ฐ์ฒด์ ์ด์์ ๊ฐ์ฒด์ธ Object
๋ก ์กฐํ์, ๋ชจ๋ ์คํ๋ง ๋น์ ์กฐํํ๋ค.
package dh0023.springcore.beanfind;
import dh0023.springcore.discount.service.DiscountPolicy;
import dh0023.springcore.discount.service.FixDiscountPolicy;
import dh0023.springcore.discount.service.RateDiscountPolicy;
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.*;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextExtendsFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด, ์ค๋ณต ์ค๋ฅ ๋ฐ์")
void findBeanByParentTypeDuplicate() {
// org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'dh0023.springcore.discount.service.DiscountPolicy' available: expected single matching bean but found 2: rateDiscountPolicy,fixDiscountPolicy
// DiscountPolicy discountPolicy = ac.getBean(DiscountPolicy.class);
assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
}
@Test
@DisplayName("๋ถ๋ชจ ํ์
์ผ๋ก ์กฐํ์, ์์์ด ๋ ์ด์ ์์ผ๋ฉด, ๋น ์ด๋ฆ์ ์ง์ ํ๋ฉด ๋๋ค.")
void findBeanByParentTypeBeanName() {
DiscountPolicy discountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
assertThat(discountPolicy).isInstanceOf(RateDiscountPolicy.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);
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 + " object " + beansOfType.get(key));
}
}
@Configuration
static class TestConfig {
/**
* @return DiscountPolicy : ์ญํ ๊ณผ ๊ตฌํ์ ๊ตฌ๋ถํ๊ธฐ ์ํด์
*/
@Bean
public DiscountPolicy rateDiscountPolicy() {
return new RateDiscountPolicy();
}
@Bean
public DiscountPolicy fixDiscountPolicy() {
return new FixDiscountPolicy();
}
}
}
BeanFactory ์ ApplicationContext ๊ด๊ณ
BeanFactory์ ApplicationContext๋ฅผ ์คํ๋ง ์ปจํ
์ด๋๋ผํ๋ค.
BeanFactory๋ฅผ ์ง์ ์ฌ์ฉํ ์ผ์ ๊ฑฐ์ ์์ผ๋ฉฐ, ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํฌํจ๋ ApplicationContext๋ฅผ ์ฌ์ฉํ๋ค.
BeanFactory
์คํ๋ง ์ปจํ
์ด๋์ ์ต์์ ์ธํฐํ์ด์ค
์คํ๋ง ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ์ญํ ์ ๋ด๋น
ApplicationContext
BeanFactory ๊ธฐ๋ฅ์ ๋ชจ๋ ์์๋ฐ์์ ์ ๊ณต
์ ํ๋ฆฌ์ผ์ด์
์ ๊ฐ๋ฐํ ๋๋ ๋น์ ๊ด๋ฆฌํ๊ณ ์กฐํํ๋ ๊ธฐ๋ฅ์ ๋ฌผ๋ก ์ด๊ณ , ์ ๋ง์ ๋ถ๊ฐ๊ธฐ๋ฅ์ด ํ์ํ๋ค.
MessageSource
: ๋ฉ์ธ์ง ์์ค๋ฅผ ํ์ฉํ ๊ตญ์ ํ ๊ธฐ๋ฅ
ํ๊ตญ์์ ์ ์์ ํ๊ตญ์ด๋ก, ์์ด๊ถ์์ ๋ค์ด์ค๋ฉด ์์ด๋ก ์ถ๋ ฅ
EnvironmentCapable
: ํ๊ฒฝ๋ณ์
local, dev, qa, stg, prod ๋ฑ์ ๊ตฌ๋ถํด์ ์ฒ๋ฆฌ
ApplicationEventPublisher
: ์ ํ๋ฆฌ์ผ์ด์
์ด๋ฒคํธ
์ด๋ฒคํธ๋ฅผ ๋ฐํํ๊ณ ๊ตฌ๋
ํ๋ ๋ชจ๋ธ์ ํธ๋ฆฌํ๊ฒ ์ง์
ResourceLoader
: ํธ๋ฆฌํ ๋ฆฌ์์ค ์กฐํ
ํ์ผ, ํด๋์คํจ์ค, ์ธ๋ถ ๋ฑ์์ ๋ฆฌ์์ค๋ฅผ ํธ๋ฆฌํ๊ฒ ์กฐํ
Bean Scope
์คํ๋ง์ด ๊ด๋ฆฌํ๋ ์ค๋ธ์ ํธ(=๋น)์ Scope๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ๊ธํค์ด๋ค.
Singleton Scope : ์ปจํ
์ด๋ ๋ด์ ํ๊ฐ์ ์ค๋ธ์ ํธ๋ง ๋ง๋ค์ด์ ธ ๊ฐ์ ๋ก ์ ๊ฑฐํ์ง ์๋ ํ ์คํ๋ง ์ปจํ
์ด๋๊ฐ ์กด์ฌํ๋ ๋์ ๊ณ์ ์ ์ง๋๋ค.
์ํ๊ฐ ์๋ ๊ณต์ ๊ฐ์ฒด : ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ด์ ๊ฐ ์๋ค.
์ฝ๊ธฐ์ฉ์ผ๋ก๋ง ์ํ๋ฅผ ๊ฐ์ง ๊ณต์ ๊ฐ์ฒด : ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ ์ด์ ๊ฐ ์๋ค.
๊ณต์ ๊ฐ ํ์ํ ์ํ๋ฅผ ์ง๋ ๊ณต์ ๊ฐ์ฒด : ๊ฐ์ฒด ๊ฐ ๋ฐ๋์ ๊ณต์ ํด์ผํ ์ํ๋ฅผ ์ง๋ ๊ฐ์ฒด๊ฐ ์๋ค๋ฉด ์ด ๊ฒฝ์ฐ์๋ Singleton์ ํฉ
์ฐ๊ธฐ๊ฐ ๊ฐ๋ฅํ๋ฉด์๋ ์ฌ์ฉ๋น๋๊ฐ ๋งค์ฐ ๋์ ๊ฐ์ฒด
์ฅ์๊ฐ์ ๊ฑธ์ณ ๋งค์ฐ ๋ง์ ๊ฐ์ฒด๊ฐ ์์ฑ๋๋ ๊ฒฝ์ฐ
ํด๋น ๊ฐ์ฒด๊ฐ ๋งค์ฐ ์์ ์์ ์ฐ๊ธฐ ์ํ๋ฅผ ๊ฐ์ง ๊ฒฝ์ฐ
๊ฐ์ฒด ์์ฑ ๋น์ฉ์ด ๋งค์ฐ ํฐ ๊ฒฝ์ฐ
Prototype Scope : ์ปจํ
์ด๋์ ๋น์ ์์ฒญํ ๋๋ง๋ค ๋งค๋ฒ ์๋ก์ด ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ด์ค๋ค.(gc์ ์ํด์ bean์ด ์ ๊ฑฐ๋๋ค)
Request Scope : HTTP ์์ฒญ์ด ์๊ธธ๋๋ง๋ค ์์ฑ๋๋ ์์ฒญ ์ค์ฝํ
Session Scope : ์น์ Session๊ณผ ์ ์ฌํ ์ธ์
์ค์ฝํ
Dependency Injection
DI๋ ์์กด๊ด๊ณ ์ฃผ์
์ ๋ง ๊ทธ๋๋ก ์์กด์ ์ธ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๊ฑฐ๋ ์ ์ดํ๋ ๊ฒ์ด ์๋๋ผ, ํน์ ๊ฐ์ฒด์ ํ์ํ ๊ฐ์ฒด๋ฅผ ์ธ๋ถ์์ ๊ฒฐ์ ํด์ ์ฐ๊ฒฐ์ํค๋ ๊ฒ์ ์๋ฏธํ๋ค.
์ธํฐํ์ด์ค์ ๋ํด์๋ง ์์กด๊ด๊ณ๋ฅผ ๋ง๋ค์ด๋๋ฉด ์ธํฐํ์ด์ค ๊ตฌํ ํด๋์ค์์ ๊ด๊ณ๋ ๋์จํด์ง๋ฉด์ ๋ณํ์ ์ํฅ์ ๋ ๋ฐ๋ ์ํ(= ๊ฒฐํฉ๋๊ฐ ๋ฎ์ ์ํ)๊ฐ ๋๋ค. ์์กด๊ด๊ณ๋ ํ์ชฝ์ ๋ณํ๊ฐ ๋ค๋ฅธ ์ชฝ์ ์ํฅ์ ์ฃผ๋ ๊ฒ์ธ๋ฐ, ์ธํฐํ์ด์ค๋ฅผ ํตํด ์์กด ๊ด๊ณ๋ฅผ ์ ์ํด์ฃผ๋ฉด ๊ทธ๋งํผ ๋ณํ๋ก๋ถํฐ ์์ ๋ก์์ง ์ ์๋ค.
๋ฐํ์ ์์ ์ค๋ธ์ ํธ ์ฌ์ด์์ ๋ง๋ค์ด์ง๋ ์์กด๊ด๊ณ๋ ์๋ค. ๋ฐํ์ ์์กด๊ด๊ณ ํน์ ์ค๋ธ์ ํธ ์์กด ๊ด๊ณ์ธ๋ฐ, ์ค๊ณ ์์ ์ ์์กด๊ด๊ณ๊ฐ ์ค์ฒดํ๋ ๊ฒ์ผ๋ก ๋ณผ ์ ์๋ค.
์ธํฐํ์ด์ค๋ฅผ ํตํด ์ค๊ณ ์์ ์ ๋์จํ ์์กด๊ด๊ณ๋ฅผ ๊ฐ๋ ๊ฒฝ์ฐ์๋ ๋ฐํ์ ์์ ์ฌ์ฉํ ์ค๋ธ์ ํธ๊ฐ ์ด๋ค ํด๋์ค๋ก ๋ง๋ ๊ฒ์ธ์ง ๋ฏธ๋ฆฌ ์ ์ ์๋ค. ํ๋ก๊ทธ๋จ์ด ์์๋๊ณ ์ค๋ธ์ ํธ๊ฐ ๋ง๋ค์ด์ง๊ณ ๋์ ๋ฐํ์ ์์ ์์กด ๊ด๊ณ๋ฅผ ๋งบ๋ ๋์์ ์์กด ์ค๋ธ์ ํธ(dependent object)๋ผ๊ณ ํ๋ค.
์ฆ, ์์กด ๊ด๊ณ ์ฃผ์
์ ์์กด ์ค๋ธ์ ํธ์ ๊ทธ๊ฒ์ ์ฌ์ฉํ ์ฃผ์ฒด ์ค๋ธ์ ํธ๋ฅผ ๋ฐํ์ ์์ ์ฐ๊ฒฐํด์ฃผ๋ ์์
์ ๋งํ๋ค.
ํด๋์ค ๋ชจ๋ธ์ด๋ ์ฝ๋์์ ๋ฐํ์ ์์ ์ ์์กด ๊ด๊ณ๊ฐ ๋๋ฌ๋์ง ์๋๋ค. ๊ทธ๋ฌ๊ธฐ ์ํด์๋ ์ธํฐํ์ด์ค์๋ง ์์กดํ๊ณ ์์ด์ผํ๋ค.
๋ฐํ์ ์์ ์ ์์กด๊ด๊ณ๋ ์ปจํ
์ด๋๋ ํฉํ ๋ฆฌ ๊ฐ์ ์ 3์ ์กด์ฌ๊ฐ ๊ฒฐ์ ํ๋ค.
์์กด ๊ด๊ณ๋ ์ฌ์ฉํ ์ค๋ธ์ ํธ์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ์ธ๋ถ์์ ์ ๊ณตํด์ค์ผ๋ก์จ ๋ง๋ค์ด์ง๋ค.
์ฆ, ์์กด๊ด๊ณ ์ฃผ์
์ ์ฌ์ฉํ๋ฉด ์ ์ ์ธ ํด๋์ค ์์กด๊ด๊ณ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ , ๋์ ์ธ ๊ฐ์ฒด ์ธ์คํด์ค ์์กด๊ด๊ณ๋ฅผ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์๋ค.
์์กด๊ด๊ณ ์ฃผ์
(DI)์ ํต์ฌ์ ์ค๊ณ ์์ ์ ์์ง ๋ชปํ๋ ๋ ์ค๋ธ์ ํธ์ ๊ด๊ณ๋ฅผ ๋งบ๋๋ก ๋์์ฃผ๋ ์ 3์ ์กด์ฌ๊ฐ ์๋ค๋ ๊ฒ์ด๋ค. ์ฌ๊ธฐ์ ์ 3์ ์กด์ฌ๋ ๋ฐ๋ก ์ ํ๋ฆฌ์ผ์ด์
์ปจํ
์คํธ, ๋น ํฉํ ๋ฆฌ, IoC ์ปจํ
์ด๋๋ผ๊ณ ๋ณผ ์ ์๋ค.
์คํ๋ง์ DI๋ฅผ ์ฌ์ฉํ๋ฉด "๊ธฐ์กด ์ฝ๋๋ฅผ ์ ํ ์๋์ง ์๊ณ , ์ค์ ๋ง์ผ๋ก ๊ตฌํ ํด๋์ค๋ฅผ ๋ณ๊ฒฝ"ํ ์ ์๋ค.
์ ์ ํด๋์ค ์์กด ๊ด๊ณ
ํด๋์ค๊ฐ ์ฌ์ฉํ๋ import ์ฝ๋๋ง ๋ณด๊ณ ์์กด๊ด๊ณ๋ฅผ ์ฝ๊ฒ ํ๋จํ ์ ์๋ค. ์ ์ ์ธ ์์กด๊ด๊ณ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ์ง ์์๋ ๋ถ์ํ ์ ์๋ค. ํด๋์ค ๋ค์ด์ด๊ทธ๋จ์ ์๊ฐํ๋ฉด ๋๋ค.
XML์ ์ด์ฉํ ์ค์
์ต๊ทผ์๋ ์คํ๋ง ๋ถํธ๋ฅผ ๋ง์ด ์ฌ์ฉํ๋ฉด์ XML๊ธฐ๋ฐ์ ์ค์ ์ ์ ์ฌ์ฉํ์ง ์๋๋ค. ํ์ง๋ง, ์์ง ๋ง์ ๋ ๊ฑฐ์ ํ๋ก์ ํธ์์ XML๋ก ์ค์ ๋์ด์๋ค. XML ์ฌ์ฉ์ ์ปดํ์ผ ์์ด ๋น ์ค์ ์ ๋ณผ๋ฅด ๋ณ๊ฒฝํ ์ ์์ผ๋ฏ๋ก ์์๋๋ ๊ฒ์ด ์ข๋ค.
XML์ผ๋ก ์์กด๊ด๊ณ ์ค์ ์ ๋ณด๋ฅผ ๋ง๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ์ฅ์ ์ด ์๋ค.
๋จ์ํ ํ
์คํธ ํ์ผ์ด๊ธฐ๋๋ฌธ์ ๋ค๋ฃจ๊ธฐ ์ฌ์
์ฝ๊ฒ ์ดํดํ ์ ์์ผ๋ฉฐ, ์ปดํ์ผ๊ณผ ๊ฐ์ ๋ณ๋์ ๋น๋ ์์
์ด ์์
๋น ๋ฅด๊ฒ ๋ณ๊ฒฝ์ฌํญ์ ๋ฐ์ํ ์ ์์
์คํค๋ง๋ DTD๋ฅผ ์ด์ฉํด ์ ํด์ง ํฌ๋งท์ ๋ฐ๋ผ ์์ฑํ๋์ง ์ฝ๊ฒ ํ์ธ ๊ฐ๋ฅ
GenericXmlApplicationContext
๋ฅผ ์ฌ์ฉํ๋ฉด์ xml
์ค์ ํ์ผ์ ๋๊ธฐ๋ฉด ๋๋ค.
์คํ๋ง์ application context๋ XML์ ๋ด๊ธด DI์ ๋ณด๋ฅผ ํ์ฉํ ์ ์๋ค. ์์์ ๋ค๋ค๋ @Configuration
์ <beans>
, @bean
์ <bean>
์ผ๋ก ๋์ํด์ ์๊ฐํ๋ฉด ์ดํดํ๊ธฐ ์ฝ๋ค.
package dh0023.springcore.config;
import dh0023.springcore.discount.service.DiscountPolicy;
import dh0023.springcore.discount.service.RateDiscountPolicy;
import dh0023.springcore.member.repository.MemberRepository;
import dh0023.springcore.member.repository.MemoryMemberRepository;
import dh0023.springcore.member.service.MemberService;
import dh0023.springcore.member.service.MemberServiceImpl;
import dh0023.springcore.order.service.OrderService;
import dh0023.springcore.order.service.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* ์ ํ๋ฆฌ์ผ์
์ ์ค์ ๋์์ ํ์ํ ๊ตฌํ ๊ฐ์ฒด ์์ฑ
* ์์ฑํ ๊ฐ์ฒด ์ธ์คํด์ค์ ์ฐธ์กฐ๋ฅผ ์์ฑ์๋ฅผ ํตํด ์ฃผ์
ํด์ค๋ค.
*/
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(getMemberRepository());
}
@Bean
public MemberRepository getMemberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService(){
return new OrderServiceImpl(getMemberRepository(), getDiscountPolicy());
}
@Bean
public DiscountPolicy getDiscountPolicy() {
return new RateDiscountPolicy();
}
}
<?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="dh0023.springcore.member.service.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
</bean>
<bean id="memberRepository" class="dh0023.springcore.member.repository.MemoryMemberRepository" />
<bean id="orderService" class="dh0023.springcore.order.service.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
<constructor-arg name="discountPolicy" ref="discountPolicy"/>
</bean>
<bean id="discountPolicy" class="dh0023.springcore.discount.service.RateDiscountPolicy" />
</beans>
package dh0023.springcore.xml;
import dh0023.springcore.member.service.MemberService;
import dh0023.springcore.member.service.MemberServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.context.support.GenericXmlApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
public class XmlAppContext {
@Test
void xmlAppContext() {
GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
}
BeanDefinition - ๋น ์ค์ ๋ฉํ ์ ๋ณด
์คํ๋ง์ BeanDefinition
์ธํฐํ์ด์ค๋ฅผ ์ค์ฌ์ผ๋ก ๋ค์ํ ์ค์ ํ์์ ์ง์ํ๊ณ ์๋ค. ์ฝ๊ฒ ๋งํด BeanDefinition
์ ๋ฉํ ์ ๋ณด๋ฅผ ๊ธฐ์ตํ๋ ์ญํ ์ ํ๊ณ ์์ผ๋ฉฐ, ์คํ๋ง ์ปจํ
์ด๋๋ ์๋ฐ์ฝ๋๋ก ์ค์ ์ด ๋๊ฑด์ง, XML ํ์ผ๋ก ์ค์ ์ด ๋๊ฑด์ง ๋ชฐ๋ผ๋ ๋๋ค.
BeanDefinition
์ ๋น ์ค์ ๋ฉํ ์ ๋ณด๋ผ ํ๋ฉฐ, @Bean
, <bean>
๋น ๊ฐ๊ฐ ํ๋์ ๋ฉํ ์ ๋ณด๊ฐ ์์ฑ๋๋ค. ์คํ๋ง ์ปจํ
์ด๋๋ ์ด ๋ฉํ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํ๋ง ๋น์ ์์ฑํ๋ค.
AnnotaionConfigApplicationContext
๋ AnnotatedBeanDefinitionReader
๋ฅผ ์ฌ์ฉํด AppConfig.class
(@Configuration
ํ์ผ) ๋ฅผ ์ฝ๊ณ BeanDefinition
์ ์์ฑํ๋ค.
GenericXmlApplicationContext
๋ XmlBeanDefinitionReader
๋ฅผ ์ฌ์ฉํด appConfig.xml
๋ฅผ ์ฝ๊ณ BeanDefinition
์ ์์ฑํ๋ค.
์๋ก์ด ํ์์ ๊ฒฝ์ฐ์๋ XxxBeanDefinitionReader
๋ฅผ ์์ฑํ์ฌ, BeanDefinition
์ ์์ฑํ๋ฉด ๋๋ค.
์ ๋ณด
package dh0023.springcore.beandefinition;
import dh0023.springcore.config.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 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);
}
}
}
}
// Java Config
// ์๋ฐ ์ค์ ์ ํฉํ ๋ฆฌ ๋ฉ์๋ ๋ฐฉ์์ผ๋ก ์์ฑ
BeanDefinitionName = appConfig beanDefinition = Generic bean: class [dh0023.springcore.config.AppConfig$$EnhancerBySpringCGLIB$$eadd5c79]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
BeanDefinitionName = memberService beanDefinition = Root 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 dh0023.springcore.config.AppConfig
BeanDefinitionName = getMemberRepository beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=getMemberRepository; initMethodName=null; destroyMethodName=(inferred); defined in dh0023.springcore.config.AppConfig
BeanDefinitionName = orderService beanDefinition = Root 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 dh0023.springcore.config.AppConfig
BeanDefinitionName = getDiscountPolicy beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=getDiscountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in dh0023.springcore.config.AppConfig
package dh0023.springcore.beandefinition;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDefinitionTest {
GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
@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);
}
}
}
}
// xml Config
BeanDefinitionName = memberService beanDefinition = Generic bean: class [dh0023.springcore.member.service.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 beanDefinition = Generic bean: class [dh0023.springcore.member.repository.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 beanDefinition = Generic bean: class [dh0023.springcore.order.service.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 beanDefinition = Generic bean: class [dh0023.springcore.discount.service.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]
BeanClassName: ์์ฑํ ๋น์ ํด๋์ค ๋ช
(์๋ฐ ์ค์ ์ฒ๋ผ ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฉด ์์)
factoryBeanName: ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ด๋ฆ, ์) appConfig
factoryMethodName: ๋น์ ์์ฑํ ํฉํ ๋ฆฌ ๋ฉ์๋ ์ง์ , ์) memberService
Scope: ์ฑ๊ธํค(๊ธฐ๋ณธ๊ฐ)
lazyInit: ์คํ๋ง ์ปจํ
์ด๋๋ฅผ ์์ฑํ ๋ ๋น์ ์์ฑํ๋ ๊ฒ์ด ์๋๋ผ, ์ค์ ๋น์ ์ฌ์ฉํ ๋ ๊น์ง ์ต๋ํ ์์ฑ์ ์ง์ฐ์ฒ๋ฆฌ ํ๋์ง ์ฌ๋ถ
InitMethodName: ๋น์ ์์ฑํ๊ณ , ์์กด๊ด๊ณ๋ฅผ ์ ์ฉํ ๋ค์ ํธ์ถ๋๋ ์ด๊ธฐํ ๋ฉ์๋ ๋ช
DestroyMethodName: ๋น์ ์๋ช
์ฃผ๊ธฐ๊ฐ ๋๋์ ์ ๊ฑฐํ๊ธฐ ์ง์ ์ ํธ์ถ๋๋ ๋ฉ์๋ ๋ช
Constructor arguments, Properties: ์์กด๊ด๊ณ ์ฃผ์
์์ ์ฌ์ฉ (์๋ฐ ์ค์ ์ฒ๋ผ ํฉํ ๋ฆฌ ์ญํ ์ ๋น์ ์ฌ์ฉํ๋ฉด ์์)
์ด๋ฌํ ๋ฉํ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์คํ๋ง ์ปจํ
์ด๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด๋ค.
์ค๋ฌด์์๋ BeanDefinition
์ ์ง์ ์ ์ํ๊ฑฐ๋ ์ฌ์ฉํ ์ผ์ ์์ผ๋ฏ๋ก, ์คํ๋ง์ด ๋ค์ํ ํํ์ ์ค์ ์ ๋ณด๋ฅผ BeanDefinition
์ ์ถ์ํํด์ ์ฌ์ฉํ๋ ๊ฒ ์ ๋๋ง ์ดํดํ๋ฉด ๋๋ค.
์ฐธ๊ณ