1. ๊ฐ์
๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์ ํด์ง์ง ์์์ ์์ ๋ฉ๋ชจ๋ฆฌ ์ ์ฅ์๋ฅผ ๊ตฌํํด์ ๊ฐ๋ฐํ๋ ์ค, DB๊ฐ ํ์ ๋๊ณ JPA๋ก ๋ ํฌ์งํฐ๋ฆฌ ๋ ์ด์ด๋ฅผ ๊ตฌํํ๋ค๊ณ ๊ฐ์ ํ๋ค. DI ์ปจํ ์ด๋, ํน์ ์คํ๋ง ์ปจํ ์ด๋์ ๋ํด ๊ณต๋ถํ๊ธฐ ์ ์๋ ์์กด๊ด๊ณ๋ฅผ ์ง์ ๊ตฌํ์ฒด๋ฅผ ์ค์ ํ์ฌ ์ง์ ํด ์ฃผ์์ง๋ง, ์ด๋ SOLID 5์์น ์ค DIP, OCP์ ์๋ฐฐ๋๋ ๋ฐฉ์์ด๋ค. ๊ทธ๋ ๋ค๋ฉด ๊ฐ์ฒด์งํฅ์ ์ธ ์ค๊ณ๋ฅผ ์ํด์๋ ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
2. ์คํ๋ง์ด ์๋ค๊ณ ๊ฐ์ ํ๋ฉด
๋จผ์ ์ฐ๋ฆฌ๊ฐ ์ต์ข ์ ์ผ๋ก ์ฑ๊ณตํด์ผ ํ๋ ํ ์คํธ ์ฝ๋๋ฅผ ๋จผ์ ์์ฑ ํด๋ณด์.
class MemberServiceImplTest {
//์์ง ๋ณ๋ค๋ฅธ DI ์ปจํ
์ด๋๊ฐ ์์ผ๋ฏ๋ก ์๋น์ค ๊ฐ์ฒด๋ ์ง์ ์์ฑํ์ฌ ์ฃผ์
ํ๋๋ก ํ๋ค.
MemberService memberService = new MemberServiceImpl();
@Test
@DisplayName("ํ์๊ฐ์
์ฑ๊ณต")
void join() {
//given
Member member = new Member("name", MemberGrade.USER);
//when
Long joinedId = memberService.join(member);
//then
Member findMember = memberService.findOne(joinedId).get();
Assertions.assertThat(findMember.getId()).isEqualTo(member.getId());
Assertions.assertThat(findMember.getGrade()).isEqualTo(member.getGrade());
}
}
๋ง์ฝ ์คํ๋ง์ ๊ธฐ๋ฅ์ด ์์ด ๊ตฌํ์ฒด๋ฅผ ์ค์ ํ๋ค๊ณ ํ๋ฉด ๋ค์๊ณผ ๊ฐ์ด ๋คํ์ฑ์ ์ด์ฉํด๋ณผ ์ ์๋ค.
public class MemberServiceImpl implements MemberService {
// private MemberRepository memberRepository = new MemoryMemberRepository();
private MemberRepository memberRepository = new JpaMemberRepository();
// ์ดํ ์๋น์ค ๋ก์ง
๋ค์๊ณผ ๊ฐ์ด ์์กด์ฑ์ ์ง์ ์์ ํด ์ฃผ์๋ค๋ฉด ํ ์คํธ ์ฝ๋๋ ์ ํต๊ณผํ ๊ฒ์ด๋ค.
ํ์ง๋ง ์์ ๊ฐ์ ์ฝ๋๋ ์ฌ์ค ์์์ ์์ ํ๋ฏ DIP, OCP ์์น์ ์๋ฐฐ๋๋ค.
DIP - ์์กด๊ด๊ณ ์ญ์ ์์น
์ถ์ํ์ ์์กดํด์ผ ํ๊ณ , ๊ตฌ์ฒดํ์ ์์กดํ๋ฉด ์๋๋ค.
OCP - ๊ฐ๋ฐฉ-ํ์ ์์น
ํ์ฅ์๋ ์ด๋ ค์์ผ๋ ๋ณ๊ฒฝ์๋ ๋ซํ์์ด์ผ ํ๋ค.
์๋น์ค ๊ฐ์ฒด๋ ๋น์ง๋์ค ๋ก์ง์ ์ง์ค ํด์ผํ๊ณ , ์์ ์ด ์ง์ ๋ด๋ถ์ ์ด๋ค ๊ตฌํ์ฒด๋ฅผ ์ ํํ ์ง ๊ฒฐ์ ํ๋ฉด ์๋๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ ํ ๋ฐฉ์์ผ๋ก ์๋น์ค ๊ฐ์ฒด ๋ด๋ถ์ ์ง์ ์์กด๊ด๊ณ๋ฅผ ์ค์ ํ์ง ์๊ณ ๊ฐ๋ฐ์์ ์๋๋๋ก ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ ํ ์ ์์๊น?
์ฐ์ ์ง์ ์ ์ธ ์์กด์ฑ ์ฃผ์ ์ฝ๋๋ฅผ ์ญ์ ํด๋ณด๋๋ก ํ์.
public class MemberServiceImpl implements MemberService {
private MemberRepository memberRepository;
// ์ดํ ์๋น์ค ๋ก์ง
๋ค์๊ณผ ๊ฐ์ด ์์ ํ๊ณ ํ ์คํธ ์ฝ๋๋ฅผ ์คํํ๋ค๋ฉด ๋น์ฐํ memberRepository ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ๋ NullpointerException์ด ๋ฐ์ํ๋ค.
์๋ํ๋ฉด ์๋ฌด๋ memberRepository ๊ฐ์ฒด๋ฅผ ์ฃผ์ ํด์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ด๋ค.
๊ทธ๋์ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ค์ ์์ธ Config ๊ฐ์ฒด์ ๊ฐ๋ ์ด ๋ฑ์ฅํ๊ฒ ๋๋ค.
๋ค์๊ณผ ๊ฐ์ MemberConfig ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.
public class MemberConfig {
public MemberRepository memberRepository() {
return new JpaMemberRepository();
}
public MemberService memberService() {
return new MemberServiceImpl();
}
}
Member ๋๋ฉ์ธ์ ๊ดํ ์ค์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ ์์กด๊ด๊ณ ์ฃผ์ ์ ์ด Config ๊ฐ์ฒด์๊ฒ ์์ ํ ์ผ์ํ๋ ๊ฒ์ด๋ค.
๊ทธ๋ ๋ค๋ฉด MemberServiceImpl ํด๋์ค ๋ด๋ถ์ ์์กด์ฑ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ํ ์ ์๋ค.
public class MemberServiceImpl implements MemberService {
private MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// ์ดํ ์๋น์ค ๋ก์ง
class MemberServiceImplTest {
MemberService memberService;
@BeforeEach
void beforeEach() {
//Config ๊ฐ์ฒด๋ฅผ ํตํด ์์กด์ฑ์ ์ฃผ์
๋ฐ๋๋ค.
MemberConfig memberConfig = new MemberConfig();
this.memberService = memberConfig.memberService();
}
์ด๋ ๊ฒ MemberConfig ๊ฐ์ฒด๋ฅผ ํตํด ์์กด๊ด๊ณ๋ฅผ ์ฃผ์ ๋ฐ๋๋ค๋ฉด, ์๋ฌด๋ฆฌ MemberRepository ์ธํฐํ์ด์ค์ ๋ํ ๊ตฌํ์ฒด๊ฐ ๋ฐ๋์ด๋ Config ๊ฐ์ฒด ๋ด๋ถ์์๋ง ์์กด๊ด๊ณ๋ฅผ ์ ํํ๊ณ , ์๋น์ค ๊ฐ์ฒด ๋ด๋ถ์ ์ง์ ์์กด๊ด๊ณ๋ฅผ ์ ํํ ์ผ์ด ์ฌ๋ผ์ง๊ฒ ๋๋ค.
์ฆ, ์์กด๊ด๊ณ ์ ํ ์ฑ ์์ ์์ ํ ์ผ์ํ๋ ๊ฒ์ด๋ค.
์ด์ฒ๋ผ ํ๋ก๊ทธ๋จ(๊ฐ์ฒด)์ด ๊ตฌํ ๊ฐ์ฒด ์ ์ด๋ฅผ ์ง์ ํ์ง ์๊ณ , ์ธ๋ถ์์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์ ์ด์ ์ญ์ IoC(Inversion of Control) ์ด๋ผ๊ณ ํ๋ค.
๋ํ MemberConfig ์ฒ๋ผ ์ ์ด ํ๋ฆ์ ๋ํ ๊ถํ์ ๊ฐ์ง๊ณ ์๋ ์ญํ ์ ๊ฐ์ฒด๋ฅผ IoC ์ปจํ ์ด๋ ํน์ DI ์ปจํ ์ด๋๋ผ๊ณ ํ๋ค.
์ด๋ ๊ฒ ์ฑ ์์ ๋ถ๋ฆฌํ๊ฒ ๋๋ค๋ฉด ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๊ฐ ๋๋ค.
์ด์ OCP ์์น๊ณผ DIP ์์น์ ์ค์ํ ์ ์๊ฒ ๋์์ง๋ง, ํ์ฌ๋ ์คํ๋ง์ ๋์ ์์ด ๊ตฌํํ์๊ธฐ ๋๋ฌธ์ ์ฑ๊ธํค ํจํด๋ ์ค์๋์ง ์๊ณ ์๊ณ , ์ฌ์ฉ์๊ฐ ์ผ์ผํ ์์กด์ฑ์ ์ค์ ํด์ฃผ์ด์ผ ํ๋ ๋ฌธ์ ๊ฐ ๋จ์์๋ค.
์์ ์๋น์ค๋ผ๋ ์๋นํ ๋ง์ ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๊ฐ ์์ฑ๋ ํ ๋ฐ ๋ชจ๋ ์์กด์ฑ์ ์ฌ์ฉ์๊ฐ Config ๊ฐ์ฒด์ ์ง์ ์ฃผ์ ํด์ผ ํ ๊น?
3. ์คํ๋ง ์ปจํ ์ด๋
๊ธฐ์กด ์์ค์์๋ ์ฐ๋ฆฌ๊ฐ ์ง์ DI ์ปจํ ์ด๋๋ฅผ ์์ฑํ์ฌ ์๋์ผ๋ก ๋ฑ๋ก๋ ๊ฐ์ฒด์ ์ฐธ์กฐ๊ฐ์ ๋ฐ์์์ ์ฌ์ฉํ์๋ค.
ํ์ง๋ง ์คํ๋ง์์ ์ง์ํ๋ ์คํ๋ง DI ์ปจํ ์ด๋ (์์ผ๋ก ์คํ๋ง ์ปจํ ์ด๋๋ผ ํ๊ฒ ์)๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ฌํ ๊ฐ์ฒด๋ค์ '์คํ๋ง ๋น' ์ผ๋ก ๋ฑ๋กํ์ฌ ์ ์ฅํด์ฃผ๊ณ ํธ๋ฆฌํ๊ฒ ๊ฐ์ฒด๋ค์ ์ฃผ์ ํ์ฌ ์ฌ์ฉํ ์ ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ด๋ป๊ฒ ์คํ๋ง ์ปจํ ์ด๋์ ๋น์ ๋ฑ๋กํ ์ ์์๊น?
Spring Boot ์ดํ๋ฆฌ์ผ์ด์ ์ ์์ํ ๋ ์ปดํฌ๋ํธ ์ค์บ์ด๋ผ๋ ๋์์ด ์ผ์ด๋๋๋ฐ ์ด ๋ ์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ง์ ๋ฒ์์ ํฌํจ๋ ๊ฐ์ฒด๋ค์ ๋ชจ๋ ์ค์บํ์ฌ ์คํ๋ง ์ปจํ ์ด๋์ ๋น์ผ๋ก ํฌํจ์ํจ๋ค.
์ด ์ปดํฌ๋ํธ ์ค์บ์ ๋ํด์๋ ์ถํ ํ์ ํ๋๋ก ํ๊ณ , ์ปดํฌ๋ํธ ์ค์บ์ ์ํ๋ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ํฌํจ์ํค๋ ๋ฐฉ๋ฒ์ ์ฐ์ ์ ๋ฆฌํด๋ณด์.
ํฌ๊ฒ ๋๋์๋ฉด ์๋์ผ๋ก ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ๊ณผ ์๋์ผ๋ก ๋ฑ๋ก ๋์์ ํฌํจ์ํค๋ ๋ฐฉ๋ฒ์ด ์๋ค.
3.1 ์๋ ๋ฑ๋ก
์์ ์ดํด๋ณธ Config ๊ฐ์ฒด, ์ฆ DI ์ปจํ ์ด๋๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ์์ ์์ฑํ MemberConfig ๊ฐ์ฒด์ ๋ค์๊ณผ ๊ฐ์ด @Configuration ์ ์ถ๊ฐํ๊ณ , ์์กด์ฑ์ ๋ฐํํ ๋ฉ์๋์ @Bean ์ ๋ ธํ ์ด์ ์ ์ถ๊ฐํ์.
@Configuration
public class MemberConfig {
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
}
๋ค์๊ณผ ๊ฐ์ด @Configuration ๊ณผ @Bean ์ ๋ ธํ ์ด์ ์ ํตํด DI ์ปจํ ์ด๋์ ์ฃผ์ ํ ๊ฐ์ฒด๋ค์ ๋ช ์์ ์ผ๋ก ์ง์ ํ๋ฉด, ์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ด ๊ธฐ๋๋๋ฉด์ ์์์ ๊ธฐ์ ํ ์ปดํฌ๋ํธ ์ค์บ์ ์์ง ๋์์ด ๋๋ค.
๊ทธ๋ ๋ค๋ฉด Cofig ๊ฐ์ฒด๋ฅผ ํตํด ์์งํ ๋น๋ค์ด ์คํ๋ง ์ปจํ ์ด๋์ ์ ๋๋์ง ์กฐํํ๋ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํด๋ณด๋๋ก ํ์.
public class ApplicationContextTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MemberConfig.class);
@Test
@DisplayName("์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์
๋น ์กฐํํ๊ธฐ")
void findAllBeans() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanName);
System.out.println("beanName = " + beanName + " | bean = " + bean);
}
}
}
@Test
@DisplayName("ํ์ ์๋น์ค ๋น ์ฐพ์์ค๊ธฐ")
void findMemberServiceBean() {
MemberService memberService = ac.getBean(MemberService.class);
Assertions.assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("ํ์ ๋ฆฌํฌ์งํ ๋ฆฌ ๋น ์ฐพ์์ค๊ธฐ")
void findMemberRepositoryBean() {
MemberRepository memberRepository = ac.getBean(MemberRepository.class);
Assertions.assertThat(memberRepository).isInstanceOf(MemoryMemberRepository.class);
}
}
AnnotationApplicationContext ๊ฐ์ฒด๋ ApplicationContext ์ ๊ตฌํ์ฒด ์ค ํ๋๋ก, ์คํ๋ง ๋น์ ๊ด๋ฆฌ๋ฅผ ์๋ฐ๋ก ๊ตฌํํ๋ ํ์ ์ ๊ตฌํ์ฒด์ด๋ค. ๊ณผ๊ฑฐ XML ๊ด๋ฆฌ ๋ฐฉ์ ๋ฐ Groovy ๋ฑ์ ์ด์ฉํ๋ ๊ตฌํ์ฒด๋ ์๋ค.
์๋ฐํ ๋งํ์๋ฉด ApplicationContext ๋ณด๋ค ๋น์ ๊ด๋ฆฌํ๋ BeanFactory ๊ฐ์ฒด๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ์ ์ํ๋ ๊ฒ์ด ๋ง์ง๋ง, ์ต๊ทผ์๋ BeanFactory ์์ ๊ตญ์ ํ ๊ธฐ๋ฅ, ํ๊ฒฝ๋ณ์, ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฒคํธ, ํธ๋ฆฌํ ๋ฆฌ์์ค ์กฐํ ๋ฑ ์ฌ๋ฌ ๊ธฐ๋ฅ์ ๋ง๋ถ์ธ ApplicationContext ๊ฐ์ฒด๋ฅผ ์คํ๋ง ์ปจํ ์ด๋๋ผ๊ณ ๋ถ๋ฅธ๋ค.
์์ค์ ๋ํ ์ค๋ช ์ผ๋ก ๋์๊ฐ์๋ฉด, ์คํ๋ง ์ปจํ ์ด๋์์ ์ ์ฒด ๋ฑ๋ก๋ ์คํ๋ง ๋น์ ๊ฐ์ ธ์์ ์ฌ์ฉ์๊ฐ ์ง์ ๋ฑ๋กํ ๊ฐ์ฒด (ROLE_APPLICATION) ๋ค๋ง ์ ๋ฆฌํ์ฌ ์ถ๋ ฅํ๋ค. BeanDefinition์ ๊ฐ์ฒด์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ํฌํจํ๊ณ ์๋ ๊ฐ์ฒด์ด๋ค.
์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด Config ๊ฐ์ฒด๋ฅผ ํฌํจํ์ฌ Bean์ผ๋ก ๋ฑ๋กํ ๊ฐ์ฒด๋ค์ด ์ ์ถ๋ ฅ ๋๊ณ , ์ง์ ์ง์ ํ ๊ฐ์ฒด ๋ฐํ ํ์ ์ด ์ถ๋ ฅ๋๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
3.2 ์๋ ๋ฑ๋ก
์คํ๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ํ๋ฉด์ ์ปดํฌ๋ํธ ์ค์บ์ ํตํด ๊ฐ์ฒด๋ค์ ์์งํ๊ณ ์คํ๋ง ๋น์ผ๋ก์จ ์๋์ผ๋ก ์ ์ฅํ๋ค๊ณ ์์ ์ค๋ช ํ ๋ฐ ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์๋์ผ๋ก ๋น์ผ๋ก ์์ง๋๋ ๊ฐ์ฒด๋ค์ ์ด๋ ํ ๊ฐ์ฒด๋ค์ผ๊น?
์ฌ์ค์ ์์์ ์๋ ๋ฑ๋ก์ ํ ์คํธํ๋ฉฐ ํ ๊ฐ์ง ์๋ ๋ฑ๋ก์ ์๋ฅผ ์ด๋ฏธ ์ดํด๋ณด์๋ค. ๋ฐ๋ก @Configuration ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ์ค์ ๊ฐ์ฒด์๋ค.
์คํ๋ง์์๋ ์์ฃผ ์ฐ๋ ๊ฐ์ฒด๋ค ๋ช ๊ฐ์ง๋ฅผ ๋์์ผ๋ก ํ๋ ์ ๋ ธํ ์ด์ ์ด ์กด์ฌํ๋๋ฐ ์ด ์ ๋ ธํ ์ด์ ๋ค์ ์คํ๋ง์ด ๊ธฐ๋ํ๋ฉฐ ์๋์ผ๋ก ์์งํ๋ค.
๋ํ์ ์ธ ์๋ก๋ @Configuration , @Controller , @Service , @Repository ๋ฑ์ด ์๋ค.
์ด๋ค์ ๋ชจ๋ @Component ์ ๋ ธํ ์ด์ ์ ์์๋ฐ๋๋ฐ, ๊ฒฐ๊ตญ @Component ์ ๋ ธํ ์ด์ ์ด ๋ถ์ ๊ฐ์ฒด๋ฅผ ๋ชจ๋ ์์งํ๋ค๊ณ ์ ๋ฆฌํ ์ ์๋ค.
์ ๋ ธํ ์ด์ ์ ์์์ ๊ณต์์ ์ธ ์๋ฐ ๋ฌธ๋ฒ์ด ์๋๊ณ , ์คํ๋ง์ด ํธ์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๋ค.
์๋๋ผ๋ฉด ์คํ๋ง์ด ๊ธฐ๋๋๋ฉด์ ์ปดํฌ๋ํธ ์ค์บ์ด ํ๋ฒ ์ด๋ฃจ์ด์ง์ง๋ง, ์ฐ๋ฆฌ๋ ํ ์คํธ ํ๊ฒฝ์์ ์ปดํฌ๋ํธ ์ค์บ์ ์๋์ผ๋ก ์คํํด ์ฃผ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์ค์ ํ๊ฒฝ์ ๋ง๋ค์ด ๋ณด์.
@Configuration
@ComponentScan(
basePackages = "jwjung.spring.remind",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION, classes = Configuration.class
)
)
public class MemberAutoConfig {
}
@Repository
public class MemoryMemberRepository implements MemberRepository {
// ์ดํ ์๋ต
@Service
public class MemberServiceImpl implements MemberService {
// ์ดํ ์๋ต
์ปดํฌ๋ํธ ์ค์บ๋ง์ ๋ช ์ํ๋ Config ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ค์บ์ ๋์์ด ๋ ๊ฐ์ฒด๋ค์ ๋ค์๊ณผ ๊ฐ์ด @Component์ ํ์ ์ ๋ ธํ ์ด์ ์ ๋ถ์ฌ์ค๋ค.
๊ทธ๋ฆฌ๊ณ ์๊น ํ๋ ํ ์คํธ์ ๋น์ทํ๊ฒ ํ ์คํธ๋ฅผ ์์ฑํด๋ณด์.
public class ComponentScanTest {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(MemberAutoConfig.class);
@Test
@DisplayName("์ ์ฒด ์ ํ๋ฆฌ์ผ์ด์
๋น ์กฐํํ๊ธฐ")
void findAllBeans() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanName);
System.out.println("beanName = " + beanName + " | bean = " + bean);
}
}
}
}
๋ถ๋ช Config ๊ฐ์ฒด ๋ด์ ๋ช ์ํ ์คํ๋ง ๋น์ด ์์์๋ ๋ถ๊ตฌํ๊ณ Service ๊ฐ์ฒด์ Repository ๊ฐ์ฒด๊ฐ ์คํ๋ง ๋น์ผ๋ก ์ปจํ ์ด๋ ์์ ์ ์ฅ๋์ด ์์์ ํ์ธํ ์ ์๋ค.
์ด๋ฅผ ํตํด ์ด๋ป๊ฒ ์ฌํ๊น์ง ์ผ์ผํ ๋ช ์์ ์ธ DI๋ฅผ ์ง์ ํ์ง ์์๋ ์์กด์ฑ์ด ์ฃผ์ ๋์ด ์๋์ง๋ฅผ ์์๋ณด์๋ค.
๊ทธ๋ ๋ค๋ฉด ํน์ ๊ฐ์ ๋ถ๋ชจ ์ธํฐํ์ด์ค๋ฅผ ์์๋ฐ๋ ๊ตฌํ์ฒด ๋๊ฐ๊ฐ ๋ชจ๋ ์ปดํฌ๋ํธ๋ก ๋ฑ๋ก๋์ด ์๋ค๋ฉด, ์คํ๋ง์ด MemberServiceImpl ์ ์ฃผ์ ํ ๊ฐ์ฒด๋ฅผ ์ด๋ป๊ฒ ํ๋จํ ์ ์์๊น?
MemberRepository๋ฅผ ์์๋ฐ๋ MemoryMemberRepository ์ JpaMemberRepository ์์ชฝ์ ๋ชจ๋ @Repository ์ ๋ ธํ ์ด์ ์ ๋ถ์ด๊ณ ๊ฐ์ ํ ์คํธ ๋ฉ์๋๋ฅผ ์คํํด๋ณด์.
๋ค์๊ณผ ๊ฐ์ ์น์ ํ ์๋ฌ ๋ฌธ๊ตฌ๋ฅผ ํ์ธํ ์ ์๋ค.
No qualifying bean of type 'jwjung.spring.remind.repository.MemberRepository' available: expected single matching bean but found 2: jpaMemberRepository,memoryMemberRepository
MemberServiceImpl ๊ฐ์ฒด์ ์ฃผ์ ํด์ผ ํ ์์กด์ฑ์ ์คํ๋ง์ด ํ๋จ ํ ์๊ฐ ์์ผ๋ฏ๋ก NoUniqueBeanDefinitionException ๋ฐํ์ ์์ธ๊ฐ ๋ฐ์ํ๋ค.
์ด๋ด๋ ๋๊ฐ์ง ๋ฐฉ๋ฒ์ ํตํด ๊ฐ์ฒด ์ฃผ์ ์ ํ๊ถ์ ๊ฒฐ์ ํ ์ ์๋๋ฐ, ์ฒซ๋ฒ์งธ๋ @Primary ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ, @Qualifer ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
@Primary ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ ๋งคํ ์ํฉ์ ์ฌ๋ฌ ๊ฐ์ง ๊ตฌํ์ฒด์ค, ์ค์ ๋ก ์ฃผ์ ๋ฐ์ ๊ฐ์ฒด ์์ @Primary ์ ๋ ธํ ์ด์ ์ ๋ถ์ฌ์ฃผ๋ ๊ฒ์ด๋ค.
@Repository
@Primary
public class MemoryMemberRepository implements MemberRepository {
// ์ดํ ์๋ต
๋ ํ๊ฐ์ง @Qualifer ์ ๋ ธํ ์ด์ ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์, ๊ฐ ๊ตฌํ์ฒด์ @Qualifer ์ ๋ ธํ ์ด์ ์ผ๋ก ๋ช ์นญ์ ๋ช ์ํ๊ณ , ์ค์ ๋ก ์ฃผ์ ๋ฐ๋ ๊ฐ์ฒด์๋ ์ฃผ์ ๋ฐ๋ ๋์์ @Qualifer ์ ๋ ธํ ์ด์ ์ ์ผ์น์์ผ์ฃผ๋ฉด ๋๋ค.
@Repository
@Qualifier("memoryMemberRepository")
public class MemoryMemberRepository implements MemberRepository {
// ์ดํ ์๋ต
@Repository
@Qualifier("jpaMemberRepository")
public class JpaMemberRepository implements MemberRepository {
// ์ดํ ์๋ต
@Service
public class MemberServiceImpl implements MemberService {
private MemberRepository memberRepository;
public MemberServiceImpl(@Qualifier("memoryMemberRepository")
MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// ์ดํ ์๋ต
4. ๋ง๋ฌด๋ฆฌ
์ง๊ธ๊น์ง ๊ฐ์ฒด์งํฅ์ ์ธ ์ค๊ณ๋ฅผ ๋์์ฃผ๋ ์คํ๋ง์ ๊ธฐ๋ฅ์ ์์ฐจ์ ์ผ๋ก ์์๋ณด์๋ค. ๋จ์ํ ๊ธฐ๋ฅ์ ์์กดํ ์ค๊ณ๋ณด๋ค ์คํ๋ง์ด ์ ์ด๋ฌํ ๊ธฐ๋ฅ์ ์ง์ํ๊ฒ ๋์๋์ง, ์ข์ ๊ฐ์ฒด์งํฅ ๋์์ธ์ด ์ด๋ ํ ๊ฒ์ธ์ง๋ฅผ ๊ณ ๋ คํ๋ ๊ฒ์ด ์ข์ ๊ฐ๋ฐ์๊ฐ ์๋๊น ์ถ๋ค.
ํด๋น ์๋ฆฌ์ฆ๋ ์ธํ๋ฐ์ ๊น์ํ ๊ฐ์ฌ๋ [๋งํฌ]'์คํ๋ง ํต์ฌ์๋ฆฌ - ๊ธฐ๋ณธํธ' ๊ฐ์๋ฅผ ๋ฐํ์ผ๋ก
๋ด์ฉ๊ณผ ์์ค๋ฅผ ์ฌ๊ตฌ์ฑํ์ฌ ์์ฑํ์์ต๋๋ค.