Study/Spring

@Configuration

YURI๐Ÿ•๐Ÿ“๐Ÿถ 2022. 4. 12. 18:14
๋ฐ˜์‘ํ˜•

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด

ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋”ฑ 1๊ฐœ๋งŒ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด

  • private ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์™ธ๋ถ€์—์„œ ์ž„์˜๋กœ new ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰๊ณ  getInstance ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•ด์„œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ return ํ•œ๋‹ค.
  • ์ฃผ์˜์  : ์—ฌ๋Ÿฌ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ๊ฐ™์€ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ๊ณต์œ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋Š” statefulํ•˜๊ฒŒ ์„ค๊ณ„ํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
  • ๋ฌธ์ œ์ 
    • ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ๋งŽ์ด ๋“ค์–ด๊ฐ„๋‹ค
    • ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์–ด๋ ต๋‹ค
    • ์œ ์—ฐ์„ฑ์ด ๋–จ์–ด์ง„๋‹ค
    • ์˜์กด๊ด€๊ณ„์ƒ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ตฌ์ฒด ํด๋ž˜์Šค์— ์˜์กด - DIP ์œ„๋ฐ˜
๋”๋ณด๊ธฐ

์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™ : DIP, Dependency inversion principle

  • ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์ถ”์ƒํ™”์— ์˜์กดํ•ด์•ผ์ง€, ๊ตฌ์ฒดํ™”์— ์˜์กดํ•˜๋ฉด ์•ˆ๋œ๋‹ค.
  • ๊ตฌํ˜„ ํด๋ž˜์Šค์— ์˜์กดํ•˜์ง€ ๋ง๊ณ  ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๋ผ๋Š” ๋œป

 

 

์‹ฑ๊ธ€ํ†ค ์ปจํ…Œ์ด๋„ˆ

์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๋ฉด์„œ ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ

์ฐธ๊ณ : ์Šคํ”„๋ง์˜ ๊ธฐ๋ณธ ๋นˆ ๋“ฑ๋ก ๋ฐฉ์‹์€ ์‹ฑ๊ธ€ํ†ค์ด์ง€๋งŒ, ์‹ฑ๊ธ€ํ†ค ๋ฐฉ์‹๋งŒ ์ง€์›ํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ์š”์ฒญํ•  ๋•Œ ๋งˆ๋‹ค ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ์ œ๊ณตํ•œ๋‹ค.

 

 

@Configuration๊ณผ ์‹ฑ๊ธ€ํ†ค

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์‹ฑ๊ธ€ํ†ค ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ๋‹ค. ๋”ฐ๋ผ์„œ ์Šคํ”„๋ง ๋นˆ์ด ์‹ฑ๊ธ€ํ†ค์ด ๋˜๋„๋ก ๋ณด์žฅํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

@Configuration
  public class AppConfig {
  @Bean
  public MemberService memberService() {
      return new MemberServiceImpl(memberRepository());
  }
  @Bean
  public OrderService orderService() {
      return new OrderServiceImpl(
              memberRepository(),
              discountPolicy());
}
  @Bean
  public MemberRepository memberRepository() {
      return new MemoryMemberRepository();
  }
... 
}

ํ•˜์ง€๋งŒ ์Šคํ”„๋ง์ด ์ž๋ฐ” ์ฝ”๋“œ๊นŒ์ง€ ์–ด๋–ป๊ฒŒ ํ•˜๊ธฐ๋Š” ์–ด๋ ต๋‹ค. ๊ทธ๋ž˜์„œ ์Šคํ”„๋ง์€ ํด๋ž˜์Šค์˜ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. (์œ„์˜ ์ž๋ฐ”์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด MemberRepository๊ฐ€ 3๋ฒˆ ์ƒ์„ฑ๋˜์–ด์•ผ ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋งŒ ์ƒ์„ฑ๋˜์–ด ์žˆ๋‹ค.)

@Test
void configurationDeep() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    //AppConfig๋„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.
    AppConfig bean = ac.getBean(AppConfig.class);
    System.out.println("bean = " + bean.getClass());
    //์ถœ๋ ฅ: bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$bd479d70
}

AnnotationConfigApplicationContext์— ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธด ๊ฐ’์€ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์— AppConfig๋„ ์Šคํ”„๋ง ๋นˆ์ด ๋œ๋‹ค. ํ•˜์ง€๋งŒ AppConfig์˜ ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ์ถœ๋ ฅํ–ˆ์„ ๋•Œ ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ค๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ๋‹ค (์ˆœ์ˆ˜ ํด๋ž˜์Šค๋ผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•œ๋‹ค : class hello.core.AppConfig )

 

โ—๏ธ ์ด๊ฒƒ์€ ๋‚ด๊ฐ€ ๋งŒ๋“  ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ์Šคํ”„๋ง์ด CGLIB๋ผ๋Š” ๋ฐ”์ดํŠธ์ฝ”๋“œ ์กฐ์ž‘ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ AppConfig ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ์ž„์˜์˜ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ , ๊ทธ ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ ๊ฒƒ์ด๋‹ค!

// AppConfig@CGLIB ์˜ˆ์ƒ ์ฝ”๋“œ 
@Bean
public MemberRepository memberRepository() {
    if (memoryMemberRepository๊ฐ€ ์ด๋ฏธ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด?) { 
        return ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์—์„œ ์ฐพ์•„์„œ ๋ฐ˜ํ™˜;
    } else { //์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ์—†์œผ๋ฉด
        ๊ธฐ์กด ๋กœ์ง์„ ํ˜ธ์ถœํ•ด์„œ MemoryMemberRepository๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์— ๋“ฑ๋ก return ๋ฐ˜ํ™˜
    } 
}

 

@Configuration์„ ๋ถ™์ด์ง€ ์•Š๋Š”๋‹ค๋ฉด?

@Bean๋งŒ ์‚ฌ์šฉํ•ด๋„ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋˜์ง€๋งŒ, ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. memberRepository() ์ฒ˜๋Ÿผ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ํ•„์š”ํ•ด์„œ ๋ฉ”์„œ๋“œ๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•  ๋•Œ ์‹ฑ๊ธ€ํ†ค์„ ๋ณด์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

๐Ÿ‘ Reference

๋ฐ˜์‘ํ˜•