[Spring] 7.๋‹ค์–‘ํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋ฐฉ๋ฒ•

 

1. ๋‹ค์–‘ํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋ฐฉ๋ฒ•

4๊ฐ€์ง€ ๋ฐฉ๋ฒ•

1) ์ƒ์„ฑ์ž ์ฃผ์ž…
2) ์ˆ˜์ •์ž ์ฃผ์ž… (setter ์ฃผ์ž…)
3) ํ•„๋“œ ์ฃผ์ž…
4) ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…

1) ์ƒ์„ฑ์ž ์ฃผ์ž…

- ์ƒ์„ฑ์ž ํ˜ธ์ถœ ์‹œ์ ์— ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ

- [๋ถˆ๋ณ€ / ํ•„์ˆ˜] ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ

@Component
public class OrderServiceImpl implements OrderService {
  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;
  
  @Autowired
  public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }
}

 * ์ข‹์€ ๊ฐœ๋ฐœ ์Šต๊ด€ : ์ œ์•ฝ (์ƒ์„ฑ์ž๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ / ์™ธ๋ถ€ ์ˆ˜์ • ๋ถˆ๊ฐ€๋Šฅํ•œ ๊ฒƒ์ฒ˜๋Ÿผ)

 

์ค‘์š”) ์ƒ์„ฑ์ž๊ฐ€ ํ•œ๊ฐœ๋งŒ ์žˆ์œผ๋ฉด @Autowired ์ƒ๋žต๊ฐ€๋Šฅ

@Component
public class OrderServiceImpl implements OrderService {
  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;
  
  public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }
}

 

2) ์ˆ˜์ •์ž ์ฃผ์ž… (setter ์ฃผ์ž…)

- ํ•„๋“œ๊ฐ’ ๋ณ€๊ฒฝ ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ(setter)๋ฅผ ํ†ตํ•ด์„œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹

- [์„ ํƒ / ๋ณ€๊ฒฝ] ๊ฐ€๋Šฅ์„ฑ์žˆ๋Š” ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ

@Component
public class OrderServiceImpl implements OrderService {
  private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;

  @Autowired
  public void setMemberRepository(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }
        
  @Autowired
  public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    this.discountPolicy = discountPolicy;
  }
}

- ์ƒ์„ฑ์ž ์ฃผ์ž…์˜ ๊ฒฝ์šฐ ๋นˆ์„ ๋“ฑ๋กํ•˜๋ฉด์„œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ๊ฐ™์ด ์ผ์–ด๋‚จ

- ์ˆ˜์ •์ž ์ฃผ์ž…์˜ ๊ฒฝ์šฐ ๋นˆ์„ ์„ ํƒ์ ์œผ๋กœ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…์ด ์ผ์–ด๋‚จ

 

์ฐธ๊ณ : @Autowired ์˜ ๊ธฐ๋ณธ ๋™์ž‘์€ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

         ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์–ด๋„ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด @Autowired(required = false) ๋กœ ์ง€์ •ํ•˜๋ฉด ๋œ๋‹ค.

 

์ฐธ๊ณ : ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ

์ž๋ฐ”์—์„œ๋Š” ๊ณผ๊ฑฐ๋ถ€ํ„ฐ ํ•„๋“œ์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ , setXxx, getXxx ๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ๊ทœ์น™

 

ex)

class Data {
  private int age;
  
  public void setAge(int age) {
    this.age = age;
  }
      
  public int getAge() {
    return age;
  }  
}

 

3) ํ•„๋“œ ์ฃผ์ž… 

- ํ•„๋“œ๊ฐ’ ๋ณ€๊ฒฝ ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ(setter)๋ฅผ ํ†ตํ•ด์„œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ์‹

- [์„ ํƒ / ๋ณ€๊ฒฝ] ๊ฐ€๋Šฅ์„ฑ์žˆ๋Š” ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ

@Component
public class OrderServiceImpl implements OrderService {
  @Autowired
  private MemberRepository memberRepository;
  
  @Autowired
  private DiscountPolicy discountPolicy;
}

ํŠน์ง•
- ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์„œ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์„ ์œ ํ˜นํ•˜์ง€๋งŒ ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•ด์„œ ํ…Œ์ŠคํŠธ ํ•˜๊ธฐ ํž˜๋“ฆ

- DI
ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์—†์œผ๋ฉด ์•„๋ฌด๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†๋‹ค. (์‚ฌ์šฉx)

[์ด๋Ÿด๋•Œ๋งŒ ์‚ฌ์šฉ]

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹ค์ œ ์ฝ”๋“œ์™€ ๊ด€๊ณ„ ์—†๋Š” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ
์Šคํ”„๋ง ์„ค์ •์„ ๋ชฉ์ ์œผ๋กœ ํ•˜๋Š”
@Configuration ๊ฐ™์€ ๊ณณ์—์„œ๋งŒ ํŠน๋ณ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ

 

์ฐธ๊ณ :

์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—๋Š” ๋‹น์—ฐํžˆ @Autowired๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

@SpringBootTest ์ฒ˜๋Ÿผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ํ…Œ์ŠคํŠธ์— ํ†ตํ•ฉํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

์ฐธ๊ณ :

๋‹ค์Œ ์ฝ”๋“œ์™€ ๊ฐ™์ด @Bean ์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์˜์กด๊ด€๊ณ„๋Š” ์ž๋™ ์ฃผ์ž…๋œ๋‹ค.

์ˆ˜๋™ ๋“ฑ๋ก์‹œ ์ž๋™ ๋“ฑ๋ก๋œ ๋นˆ์˜ ์˜์กด๊ด€๊ณ„๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค

@Bean
OrderService orderService(MemberRepository memberRepoisitory, DiscountPolicy discountPolicy) {
  new OrderServiceImpl(memberRepository, discountPolicy)
}

4) ์ผ๋ฐ˜ ์ฃผ์ž…

- ์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์ฃผ์ž… ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

- ํŠน์ง•

> ํ•œ ๋ฒˆ์— ์—ฌ๋Ÿฌ ํ•„๋“œ๋ฅผ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

> ์ผ๋ฐ˜์ ์œผ๋กœ ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

@Component
public class OrderServiceImpl implements OrderService {
  private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;
  
  @Autowired
  public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }
}

 

์ฐธ๊ณ :

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

์Šคํ”„๋ง ๋นˆ์ด ์•„๋‹Œ Member ๊ฐ™์€ ํด๋ž˜์Šค์—์„œ @Autowired ์ฝ”๋“œ๋ฅผ ์ ์šฉํ•ด๋„ ์•„๋ฌด ๊ธฐ๋Šฅ๋„ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.


2. ์˜ต์…˜ ์ฒ˜๋ฆฌ

- ์ฃผ์ž…ํ•  ์Šคํ”„๋ง ๋นˆ์ด ์—†์–ด๋„ ๋™์ž‘ํ•ด์•ผํ•  ๋•Œ ์žˆ์Œ

- ๊ทธ๋Ÿฐ๋ฐ @Autowired๋งŒ ์‚ฌ์šฉํ•˜๋ฉด 'required' ์˜ต์…˜ ๊ธฐ๋ณธ๊ฐ’์ด 'true' ๋ผ์„œ ์ž๋™ ์ฃผ์ž… ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์˜ค๋ฅ˜ ๋ฐœ์ƒ

 

์ž๋™ ์ฃผ์ž… ๋Œ€์ƒ์„ ์˜ต์…˜์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•

- @Autowired(required=false) : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๊ฐ€ ํ˜ธ์ถœ X

- org.springframework.lang.@Nullable : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด null์ด ์ž…๋ ฅ๋จ

- Optional<> : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด Optional.empty๊ฐ€ ์ž…๋ ฅ๋จ

 

// ํ˜ธ์ถœ ์•ˆ๋จ
@Autowired(required = false)
public void setNoBean1(Member member) {
  System.out.println("setNoBean1 = " + member);
}

// null ํ˜ธ์ถœ
@Autowired
public void setNoBean2(@Nullable Member member) {
  System.out.println("setNoBean2 = " + member);
}

// Optional.empty ํ˜ธ์ถœ
@Autowired(required = false)
public void setNoBean3(Optional<Member> member) {
  System.out.println("setNoBean3 = " + member);
}

- Member๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์•„๋‹ˆ๋‹ค.
- setNoBean1() ์€ @Autowired(required=false) ์ด๋ฏ€๋กœ ํ˜ธ์ถœ ์ž์ฒด๊ฐ€ ์•ˆ๋œ๋‹ค.

์ฐธ๊ณ :

@Nullable, Optional์€ ์Šคํ”„๋ง ์ „๋ฐ˜์— ๊ฑธ์ณ์„œ ์ง€์›๋œ๋‹ค.

ex) ์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…์—์„œ ํŠน์ • ํ•„๋“œ์—๋งŒ ์‚ฌ์šฉํ•ด๋„ ๋œ๋‹ค.


3. ์ƒ์„ฑ์ž ์ฃผ์ž… ์„ ํƒ ์ด์œ 

๊ณผ๊ฑฐ) ์ˆ˜์ •์ž ์ฃผ์ž… / ํ•„๋“œ ์ฃผ์ž…

์ตœ๊ทผ) DI ํ”„๋ ˆ์ž„์›Œํฌ -> ์ƒ์„ฑ์ž ์ฃผ์ž… ๊ถŒ์žฅ

 

1) ๋ถˆ๋ณ€

- ๋Œ€๋ถ€๋ถ„ ์˜์กด๊ด€๊ณ„ ์ฃผ๋ฆฝ์€ ํ•œ ๋ฒˆ ์ผ์–ด๋‚˜๋ฉด ์ข…๋ฃŒ์‹œ์ ๊นŒ์ง€ ์˜์กด๊ด€๊ณ„ ๋ณ€๊ฒฝํ•  ์ผ ์—†๋‹ค

- ์˜คํžˆ๋ ค ๋ณ€ํ•˜๋ฉด ์•ˆ๋œ๋‹ค

- ์ˆ˜์ •์ž ์ฃผ์ž…์€ set ๋ฉ”์„œ๋“œ public์œผ๋กœ ์—ด์–ด๋‘ฌ์•ผํ•จ

- ์ƒ์„ฑ์ž ์ฃผ์ž…์€ ๊ฐ์ฒด ์ƒ์„ฑ์‹œ ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํ˜ธ์ถœ๋จ

 

2) ๋ˆ„๋ฝ

- ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋ฅผ ๋‹จ์œ„ํ…Œ์ŠคํŠธ ํ•˜๋Š” ๊ฒฝ์šฐ

์ˆ˜์ •์ž ์ฃผ์ž…)

public class OrderServiceImpl implements OrderService {
  private MemberRepository memberRepository;
  private DiscountPolicy discountPolicy;
  
  @Autowired
  public void setMemberRepository(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }

  @Autowired
  public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    this.discountPolicy = discountPolicy;
  }
//...

@Autowired ๊ฐ€ ํ”„๋ ˆ์ž„์›Œํฌ ์•ˆ์—์„œ ๋™์ž‘ํ•  ๋•Œ๋Š” ์˜์กด๊ด€๊ณ„๊ฐ€ ์—†์œผ๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์ง€๋งŒ, ์ง€๊ธˆ์€ ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ๋กœ๋งŒ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ๋‹ค.

@Test
void createOrder() {
  OrderServiceImpl orderService = new OrderServiceImpl();
  orderService.createOrder(1L, "itemA", 10000);
}

- ์‹คํ–‰๊ฒฐ๊ณผ NullPointerException -> memberRepo / discountPolicy ๋ชจ๋‘ ์˜์กด๊ด€๊ณ„ ๋ˆ„๋ฝ

 

BUT

์ƒ์„ฑ์ž ์ฃผ์ž… ์‚ฌ์šฉํ•˜๋ฉด,

- ์ฃผ์ž… ๋ฐ์ดํ„ฐ ๋ˆ„๋ฝํ–ˆ์„๋•Œ ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ๋ฐœ์ƒ

- IDE์—์„œ ์–ด๋–ค ๊ฐ’ ํ•„์ˆ˜๋กœ ์ฃผ์ž…ํ•ด์•ผํ•˜๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ์Œ

 

final ํ‚ค์›Œ๋“œ

- ์ƒ์„ฑ์ž ์ฃผ์ž… ์‚ฌ์šฉํ•˜๋ฉด ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

- ์ƒ์„ฑ์ž์—์„œ ํ˜น์‹œ๋ผ๋„ ๊ฐ’์ด ์„ค์ •๋˜์ง€ ์•Š๋Š” ์˜ค๋ฅ˜๋ฅผ ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ง‰์•„์คŒ

 

@Component
public class OrderServiceImpl implements OrderService {
  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;

  @Autowired
  public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
  }
//...
}

 

ํ•„์ˆ˜ ํ•„๋“œ์ธ discountPolicy ์— ๊ฐ’์„ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š”๋ฐ ๋ˆ„๋ฝ

-> ์ž๋ฐ”๋Š” ์ปดํŒŒ์ผ ์‹œ์ ์— ๋‹ค์Œ ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

 

java: variable discountPolicy might not have been initialized

๊ธฐ์–ตํ•˜์ž! ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋Š” ์„ธ์ƒ์—์„œ ๊ฐ€์žฅ ๋น ๋ฅด๊ณ , ์ข‹์€ ์˜ค๋ฅ˜๋‹ค!

์ฐธ๊ณ :

์ˆ˜์ •์ž ์ฃผ์ž…์„ ํฌํ•จํ•œ ๋‚˜๋จธ์ง€ ์ฃผ์ž… ๋ฐฉ์‹์€ ๋ชจ๋‘ ์ƒ์„ฑ์ž ์ดํ›„์— ํ˜ธ์ถœ๋˜๋ฏ€๋กœ, ํ•„๋“œ์— final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

์˜ค์ง ์ƒ์„ฑ์ž ์ฃผ์ž… ๋ฐฉ์‹๋งŒ final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ •๋ฆฌ

- ์ƒ์„ฑ์ž ์ฃผ์ž… = ํ”„๋ ˆ์ž„์›Œํฌ์— ์˜์กดํ•˜์ง€ ์•Š๊ณ , ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์–ธ์–ด์˜ ํŠน์ง•์„ ์ž˜ ์‚ด๋ฆฌ๋Š” ๋ฐฉ๋ฒ•
- ๊ธฐ๋ณธ์œผ๋กœ ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๊ณ , ํ•„์ˆ˜ ๊ฐ’์ด ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š” ์ˆ˜์ •์ž ์ฃผ์ž… ๋ฐฉ์‹์„ ์˜ต์…˜์œผ๋กœ ๋ถ€์—ฌ

- ์ƒ์„ฑ์ž ์ฃผ์ž…๊ณผ ์ˆ˜์ •์ž ์ฃผ์ž…์„ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํ•ญ์ƒ ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํƒ / ์˜ต์…˜์ด ํ•„์š”ํ•˜๋ฉด ์ˆ˜์ •์ž ์ฃผ์ž…์„ ์„ ํƒ

- ํ•„๋“œ ์ฃผ์ž…์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฒŒ ์ข‹์Œ


4. ๋กฌ๋ณต๊ณผ ์ตœ์‹  ํŠธ๋ Œ๋“œ 

๋Œ€๋ถ€๋ถ„ ์ƒ์„ฑ์ž ๋ถˆ๋ณ€ / ์ƒ์„ฑ์ž์— final ํ‚ค์›Œ๋“œ ์‚ฌ์šฉ  -> ์ƒ์„ฑ์ž ๋งŒ๋“ค๊ณ , ์ฃผ์ž… ๋ฐ›์€ ๊ฐ’ ๋Œ€์ž… ์ฝ”๋“œ ๋งŒ๋“ค๊ธฐ = ๊ท€์ฐฎ

[์ตœ์ ํ™”]

> ๊ธฐ๋ณธ์ฝ”๋“œ

@Component
public class OrderServiceImpl implements OrderService {
  private final MemberRepository memberRepository;
  private final DiscountPolicy discountPolicy;
  
  @Autowired // ์ƒ์„ฑ์ž ํ•œ ๊ฐœ๋ฉด ์ƒ๋žต ๊ฐ€๋Šฅ
  public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }
}

 

> ๋กฌ๋ณต ์ ์šฉ

๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ œ๊ณตํ•˜๋Š” @RequiredArgsConstructor ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด final์ด ๋ถ™์€ ํ•„๋“œ๋ฅผ ๋ชจ์•„์„œ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด ์คŒ

(๋‹ค์Œ ์ฝ”๋“œ์—๋Š” ๋ณด์ด์ง€ ์•Š์ง€๋งŒ ์‹ค์ œ ํ˜ธ์ถœ ๊ฐ€๋Šฅ)

@Component
@RequiredArgsConstructor
  public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
}

๋กฌ๋ณต์ด ์ž๋ฐ”์˜ ์• ๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์„œ๋ผ๋Š” ๊ธฐ๋Šฅ์„ ์ด์šฉํ•ด์„œ ์ปดํŒŒ์ผ ์‹œ์ ์— ์ƒ์„ฑ์ž ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ƒ์„ฑ

์‹ค์ œ class ์—ด์–ด๋ณด๋ฉด ๋‹ค์Œ ์ฝ”๋“œ ์ถ”๊ฐ€๋˜์žˆ๋Š” ๊ฒƒ ํ™•์ธ ๊ฐ€๋Šฅ

public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
      this.memberRepository = memberRepository;
      this.discountPolicy = discountPolicy;
  }

 

์ •๋ฆฌ)

์ตœ๊ทผ์—๋Š” ์ƒ์„ฑ์ž๋ฅผ ๋”ฑ 1๊ฐœ ๋‘๊ณ , @Autowired ๋ฅผ ์ƒ๋žตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฃผ๋กœ ์‚ฌ์šฉ

์—ฌ๊ธฐ์— Lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ @RequiredArgsConstructor ํ•จ๊ป˜ ์‚ฌ์šฉ (์ƒ์„ฑ์ž ์ƒ๋žตํ•ด์ฃผ๋Š” ๋กฌ๋ณต)

 

๋กฌ๋ถ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ ์šฉ ๋ฐฉ๋ฒ•

- build.gradle์— ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฐ ํ™˜๊ฒฝ ์ถ”๊ฐ€ (or spring.io์—์„œ dependecies๋กœ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ)

plugins {
      id 'org.springframework.boot' version '2.3.2.RELEASE'
      id 'io.spring.dependency-management' version '1.0.9.RELEASE'
      id 'java'
}
  group = 'hello'
  version = '0.0.1-SNAPSHOT'
  sourceCompatibility = '11'
//lombok ์„ค์ • ์ถ”๊ฐ€ ์‹œ์ž‘ configurations {
      compileOnly {
          extendsFrom annotationProcessor
} }
//lombok ์„ค์ • ์ถ”๊ฐ€ ๋
    repositories {
         mavenCentral()
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
//lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ์‹œ์ž‘
compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok' testAnnotationProcessor 'org.projectlombok:lombok' //lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ๋
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
} }
test {
    useJUnitPlatform()
}

 

1. Preferences(์œˆ๋„์šฐ File Settings) plugin lombok ๊ฒ€์ƒ‰ ์„ค์น˜ ์‹คํ–‰ (์žฌ์‹œ์ž‘)

2. Preferences Annotation Processors ๊ฒ€์ƒ‰ -> enable annotation processing ์ฒดํฌ (์žฌ์‹œ์ž‘)

3. ์ž„์˜์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  @Getter, @Setter ํ™•์ธ -> ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•ด์คŒ

@Getter
@Setter
public class Lombokk{
  private String name;
  private int age;
}

+

@ToString : toString ์ž๋™ ์ƒ์„ฑ

@RequiredArgsContructor : ์ƒ์„ฑ์ž ์ž๋™ ์ƒ์„ฑ


5. ์กฐํšŒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ - ๋ฌธ์ œ

@Autowired - ํƒ€์ž…์œผ๋กœ ์กฐํšŒ = ๋งˆ์น˜ ๋‹ค์Œ ์ฝ”๋“œ์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. (์‹ค์ œ๋กœ๋Š” ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.)

ac.getBean(DiscountPolicy.class)

ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•˜๋ฉด ์„ ํƒ๋œ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ ๋ฌธ์ œ ๋ฐœ์ƒ

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

@Component
public class RateDiscountPolicy implements DiscountPolicy {}

@Autowired
private DiscountPolicy discountPolicy

-> ์˜ค๋ฅ˜ ๋ฐœ์ƒ ( NoUniqueBeanDefinitionException )

 

ํ•ด๊ฒฐ)

ํ•˜์œ„ํƒ€์ž… ์ง€์ •? -> DIP ์œ„๋ฐ˜ + ์œ ์—ฐ์„ฑ ๋–จ์–ด์ง


6. ๋นˆ ์—ฌ๋Ÿฌ๊ฐœ ์„ ํƒ ํ•ด๊ฒฐ๋ฐฉ์•ˆ 

1)@Autowired ํ•„๋“œ๋ช… ๋งค์นญ

2) @Quilifier - @Quilifier๋ผ๋ฆฌ ๋งค์นญ -> ๋นˆ ์ด๋ฆ„ ๋งค์นญ

3) @Primary ์‚ฌ์šฉ

 

<1> @Autowired ํ•„๋“œ๋ช… ๋งค์นญ

- Autowired๋Š” ํƒ€์ž… ๋งค์นญ์„ ์‹œ๋„ํ•˜๊ณ  ์ด๋•Œ ์—ฌ๋Ÿฌ ๋นˆ์ด ์žˆ์œผ๋ฉด ํ•„๋“œ ์ด๋ฆ„ (ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„)์œผ๋กœ ๋นˆ์ด๋ฆ„์„ ์ถ”๊ฐ€ ๋งค์นญ

 

> ๊ธฐ์กด ์ฝ”๋“œ

@Autowired
private DiscountPolicy discountPolicy

> ํ•„๋“œ ๋ช…์„ ๋นˆ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝ

@Autowired
private DiscountPolicy rateDiscountPolicy

- ํ•„๋“œ ๋ช…์ด rateDiscountPolicy์ด๊ธฐ ๋•Œ๋ฌธ์— ์ •์ƒ ์ฃผ์ž…

- ํ•„๋“œ ๋ช… ๋งค์นญ์€ ๋จผ์ € ํƒ€์ž… ๋งค์นญ์„ ์‹œ๋„ํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ์— ์—ฌ๋Ÿฌ ๋นˆ์ด ์žˆ์„ ๋•Œ ์ถ”๊ฐ€๋กœ ๋™์ž‘ํ•˜๋Š” ๊ธฐ๋Šฅ

 

@Autowired ๋งค์นญ ์ •๋ฆฌ

1) ํƒ€์ž… ๋งค์นญ

2) ํƒ€์ž… ๋งค์นญ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋‘ ๊ฐœ ์ด์ƒ์ผ ๋•Œ ํ•„๋“œ๋ช…/ํŒŒ๋ผ๋ฏธํ„ฐ๋ช…์œผ๋กœ ๋นˆ ์ด๋ฆ„ ๋งค์นญ

 

<2> @Qualifier ์‚ฌ์šฉ

- ์ถ”๊ฐ€ ๊ตฌ๋ถ„์ž ๋ถ™์—ฌ์ฃผ๋Š” ๋ฐฉ์‹ (๋นˆ์ด๋ฆ„ ๋ณ€๊ฒฝ ์•„๋‹˜)

  @Component
  @Qualifier("mainDiscountPolicy")
  public class RateDiscountPolicy implements DiscountPolicy {}
  @Component
  @Qualifier("fixDiscountPolicy")
  public class FixDiscountPolicy implements DiscountPolicy {}

ex) ์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…

@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
      this.memberRepository = memberRepository;
      this.discountPolicy = discountPolicy;
}

ex) ์ˆ˜์ •์ž ์ž๋™ ์ฃผ์ž…

@Autowired
public DiscountPolicy setDiscountPolicy(@Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
      this.discountPolicy = discountPolicy;
  }

 

๋นˆ๋“ฑ๋ก์‹œ์—๋„ ๊ฐ€๋Šฅ

 @Bean
 @Qualifier("mainDiscountPolicy")
 public DiscountPolicy discountPolicy() {
    return new ...
  }

 

์ •๋ฆฌ)

1. @Qualifier๋ผ๋ฆฌ ๋งค์นญ

2. ๋นˆ ์ด๋ฆ„ ๋งค์นญ

3. NoSuchBeanDefinitionException ์˜ˆ์™ธ ๋ฐœ์ƒ

 

<3> @Primary ์‚ฌ์šฉ

- ์šฐ์„  ์ˆœ์œ„๋ฅผ ์ •ํ•˜๋Š” ๋ฐฉ๋ฒ• (์ž์ฃผ ์‚ฌ์šฉ)

 

ex) rateDiscountPolicy๊ฐ€ ์šฐ์„ ๊ถŒ ๊ฐ€์ง€๋„๋ก

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

์‚ฌ์šฉ์ฝ”๋“œ

//์ƒ์„ฑ์ž
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
      this.memberRepository = memberRepository;
      this.discountPolicy = discountPolicy;
}

//์ˆ˜์ •์ž
@Autowired
public DiscountPolicy setDiscountPolicy(DiscountPolicy discountPolicy) {
      this.discountPolicy = discountPolicy;
}

@Primary ์ž์ฃผ ์“ฐ๋Š” ์ด์œ  

-> ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜๊ด€๋ จ

    ๋ฉ”์ธ db, ๋ณด์กฐ db => ๋ฉ”์ธ / ๋ณด์กฐ ๊ฐ€์ ธ์˜ฌ๋•Œ qualifier ํ•ด์ฃผ๋Š”๊ฒŒ ๊ท€์ฐฎ์œผ๋‹ˆ ๋ฉ”์ธ db ์ปค๋„ฅ์…˜ ๊ฑธ์–ด์ค„๋•Œ primary

    ๋ณด์กฐ db์˜ ๊ฒฝ์šฐ qualifier๋‚˜ ์ง์ ‘ ์ด๋ฆ„ ์ง€์ •ํ•˜๋Š” ์‹์œผ๋กœ ์‚ฌ์šฉ

์œ„๋ž‘ ๋˜‘๊ฐ™์€ ์–˜๊ธฐ ๊ธธ๊ฒŒ
@Primary, @Qualifier
ํ™œ์šฉ
์ฝ”๋“œ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์žˆ๊ณ , ์ฝ”๋“œ์—์„œ ํŠน๋ณ„ํ•œ ๊ธฐ๋Šฅ์œผ๋กœ ๊ฐ€๋” ์‚ฌ์šฉํ•˜๋Š” ์„œ๋ธŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ปค๋„ฅ์…˜์„ ํš๋“ํ•˜๋Š” ์Šคํ”„๋ง ๋นˆ์€ @Primary ๋ฅผ ์ ์šฉํ•ด์„œ ์กฐํšŒํ•˜๋Š” ๊ณณ์—์„œ @Qualifier ์ง€์ • ์—†์ด ํŽธ๋ฆฌํ•˜๊ฒŒ ์กฐํšŒํ•˜๊ณ , ์„œ๋ธŒ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ปค๋„ฅ์…˜ ๋นˆ์„ ํš๋“ํ•  ๋•Œ๋Š” @Qualifier ๋ฅผ ์ง€์ •ํ•ด์„œ ๋ช…์‹œ์ ์œผ๋กœ ํš๋“ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๊น”๋”ํ•˜๊ฒŒ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฌผ๋ก  ์ด๋•Œ ๋ฉ”์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์Šคํ”„๋ง ๋นˆ์„ ๋“ฑ๋กํ•  ๋•Œ @Qualifier ๋ฅผ ์ง€์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์€ ์ƒ๊ด€์—†๋‹ค.

์šฐ์„ ์ˆœ์œ„
@Primary ๋Š” ๊ธฐ๋ณธ๊ฐ’ ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ด๊ณ , @Qualifier ๋Š” ๋งค์šฐ ์ƒ์„ธํ•˜๊ฒŒ ๋™์ž‘ํ•œ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ์–ด๋–ค ๊ฒƒ์ด ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ ธ๊ฐˆ๊นŒ? ์Šคํ”„๋ง์€ ์ž๋™๋ณด๋‹ค๋Š” ์ˆ˜๋™์ด, ๋„’์€ ๋ฒ”์œ„์˜ ์„ ํƒ๊ถŒ ๋ณด๋‹ค๋Š” ์ข์€ ๋ฒ”์œ„์˜ ์„ ํƒ๊ถŒ์ด ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ๊ธฐ์„œ๋„ @Qualifier ๊ฐ€ ์šฐ์„ ๊ถŒ์ด ๋†’๋‹ค.

* qualifier ๋‹จ์  : ๋ชจ๋“  ์ฝ”๋“œ์— ๋ถ™์—ฌ์ค˜์•ผํ•จ


7. Annotation ์ง์ ‘ ๋งŒ๋“ค๊ธฐ

@Qualifier("mainDiscountPolicy") ์ด๋ ‡๊ฒŒ ๋ฌธ์ž๋ฅผ ์ ์œผ๋ฉด ์ปดํŒŒ์ผ์‹œ ํƒ€์ž… ์ฒดํฌ๊ฐ€ ์•ˆ๋œ๋‹ค

-> Annotation ๋งŒ๋“ค์–ด์„œ ํ•ด๊ฒฐ

@interface

  @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
  ElementType.TYPE, ElementType.ANNOTATION_TYPE})
  @Retention(RetentionPolicy.RUNTIME)
  @Documented
  @Qualifier("mainDiscountPolicy")
  public @interface MainDiscountPolicy {
  }
@Component
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy {}
//์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
                          @MainDiscountPolicy DiscountPolicy discountPolicy) {
      this.memberRepository = memberRepository;
      this.discountPolicy = discountPolicy;
  }

//์ˆ˜์ •์ž ์ž๋™ ์ฃผ์ž…
@Autowired
public DiscountPolicy setDiscountPolicy(@MainDiscountPolicy DiscountPolicy discountPolicy) {
      this.discountPolicy = discountPolicy;
  }
์• ๋…ธํ…Œ์ด์…˜์—๋Š” ์ƒ์†์ด๋ผ๋Š” ๊ฐœ๋…์ด ์—†๋‹ค. ์ด๋ ‡๊ฒŒ ์—ฌ๋Ÿฌ ์• ๋…ธํ…Œ์ด์…˜์„ ๋ชจ์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์Šคํ”„๋ง์ด ์ง€์›ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.
@Qulifier
๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋‹ค๋ฅธ ์• ๋…ธํ…Œ์ด์…˜๋“ค๋„ ํ•จ๊ป˜ ์กฐํ•ฉํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
๋‹จ์ ์œผ๋กœ @Autowired๋„ ์žฌ์ •์˜ ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ฌผ๋ก  ์Šคํ”„๋ง์ด ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๋šœ๋ ทํ•œ ๋ชฉ์  ์—†์ด ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์žฌ์ •์˜ ํ•˜๋Š” ๊ฒƒ์€ ์œ ์ง€๋ณด์ˆ˜์— ๋” ํ˜ผ๋ž€๋งŒ ๊ฐ€์ค‘ํ•  ์ˆ˜ ์žˆ๋‹ค.

8. ์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•  ๋•Œ, List, Map

- ๋นˆ ํ•œ ๋ฒˆ์— ์กฐํšŒ์˜๋„์ ์œผ๋กœ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ ํ•„์š”ํ•  ๋•Œ ์žˆ์Œex) ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํ• ์ธ ๋น„์œจ ์„ ํƒํ•  ์ˆ˜ ์žˆ์„ ๋•Œ -> ์ „๋žตํŒจํ„ด ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ตฌํ˜„ ๊ฐ€๋Šฅ
public class AllBeanTest {
  @Test
  void findAllBean() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);
    DiscountService discountService = ac.getBean(DiscountService.class);
    Member member = new Member(1L, "userA", Grade.VIP);
    int discountPrice = discountService.discount(member, 10000, "fixDiscountPolicy");
    
    assertThat(discountService).isInstanceOf(DiscountService.class);
    assertThat(discountPrice).isEqualTo(1000);
  }
  
  static class DiscountService {
    private final Map<String, DiscountPolicy> policyMap;
    private final List<DiscountPolicy> policies;
    
    @Autowired
    public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
      this.policyMap = policyMap;
      this.policies = policies;
      System.out.println("policyMap = " + policyMap);
      System.out.println("policies = " + policies);
    }
    
    public int discount(Member member, int price, String discountCode) {
      DiscountPolicy discountPolicy = policyMap.get(discountCode);
      
      System.out.println("discountCode = " + discountCode);
      System.out.println("discountPolicy = " + discountPolicy);
      
      return discountPolicy.discount(member, price);
    } 
  }
}

[๋กœ์ง]

DiscountService๋Š” Map์œผ๋กœ ๋ชจ๋“  DiscountPolicy ๋ฅผ ์ฃผ์ž…๋ฐ›๋Š”๋‹ค.
์ด๋•Œ fixDiscountPolicy , rateDiscountPolicy ๊ฐ€ ์ฃผ์ž…๋œ๋‹ค.

discount () ๋ฉ”์„œ๋“œ๋Š” discountCode๋กœ "fixDiscountPolicy"๊ฐ€ ๋„˜์–ด์˜ค๋ฉด map์—์„œ fixDiscountPolicy ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ์•„์„œ ์‹คํ–‰ํ•œ๋‹ค.
๋ฌผ๋ก  “rateDiscountPolicy”๊ฐ€ ๋„˜์–ด์˜ค๋ฉด rateDiscountPolicy ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ์•„์„œ ์‹คํ–‰ํ•œ๋‹ค.

[์ฃผ์ž… ๋ถ„์„]

Map<String, DiscountPolicy> : map์˜ ํ‚ค์— ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์„ ๋„ฃ์–ด์ฃผ๊ณ , ๊ทธ ๊ฐ’์œผ๋กœ DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„ ๋‹ด์•„์ค€๋‹ค.
List<DiscountPolicy> : DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„ ๋‹ด์•„์ค€๋‹ค. ๋งŒ์•ฝ ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด ์—†์œผ๋ฉด, ๋นˆ ์ปฌ๋ ‰์…˜์ด๋‚˜ Map์„ ์ฃผ์ž…ํ•œ๋‹ค.

[์ฐธ๊ณ ]

์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ ์Šคํ”„๋ง ๋นˆ ๋“ฑ๋กํ•˜๊ธฐ
์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์ƒ์„ฑ์ž์— ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ๋ฐ›๋Š”๋‹ค.
์—ฌ๊ธฐ์— ํด๋ž˜์Šค ์ •๋ณด๋ฅผ ๋„˜๊ธฐ๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค๊ฐ€ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ž๋™ ๋“ฑ๋ก๋œ๋‹ค.
new AnnotationConfigApplicationContext(AutoAppConfig.class,DiscountService.class);

ใ„ด ์ด ์ฝ”๋“œ๋Š” 2๊ฐ€์ง€๋กœ ๋‚˜๋ˆ„์–ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋‹ค.

1) new AnnotationConfigApplicationContext() ๋ฅผ ํ†ตํ•ด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
2) AutoAppConfig.class , DiscountService.class ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธฐ๋ฉด์„œ ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ž๋™์œผ๋กœ
์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค.
์ •๋ฆฌํ•˜๋ฉด ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด์„œ, ํ•ด๋‹น ์ปจํ…Œ์ด๋„ˆ์— ๋™์‹œ์— AutoAppConfig , DiscountService ๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ์ž๋™ ๋“ฑ๋กํ•œ๋‹ค.

9. ์ž๋™, ์ˆ˜๋™์˜ ์˜ฌ๋ฐ”๋ฅธ ์‹ค๋ฌด ์šด์˜ ๊ธฐ์ค€

ํŽธ๋ฆฌํ•œ ์ž๋™ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉ
- @Component / @Controller / @Service / @Repository ๊ฒŒ์ธต์— ๋งž๊ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง ์ž๋™ ์Šค์บ” ์ง€์›
- ์ตœ๊ทผ ์Šคํ”„๋ง ๋ถ€ํŠธ -> ๋‹ค์–‘ํ•œ ์Šคํ”„๋ง ๋นˆ๋“ค๋„ ์กฐ๊ฑด์ด ๋งž์œผ๋ฉด ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋„๋ก ์„ค๊ณ„
 
- ์„ค์ • ์ •๋ณด ๊ธฐ๋ฐ˜์œผ๋กœ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์„ฑ ๋ถ€๋ถ„ VS ์‹ค์ œ ๋™์ž‘ํ•˜๋Š” ๋ถ€๋ถ„ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์ด ์ด์ƒ์ 
- @Component๋งŒ ๋„ฃ์–ด์ฃผ๋ฉด ๋๋‚˜๋Š” ์ผ์„ @Configuration ์„ค์ • ์ •๋ณด์—๊ฐ€์„œ @Bean ์ ๊ณ , ๊ฐ์ฒด ์ƒ์„ฑํ•˜๊ณ , ์ฃผ์ž…ํ•  ๋Œ€์ƒ ์ผ์ผ์ด ์ ์–ด์ฃผ๋Š” ๊ณผ์ • ๋ฒˆ๊ฑฐ๋กœ์›€
- ๊ด€๋ฆฌํ•  ๋นˆ์ด ๋งŽ์•„ ์„ค์ • ์ •๋ณด ๊ด€๋ฆฌ ํž˜๋“ค์–ด์งˆ์ˆ˜๋„
- ์ž๋™ ๋นˆ์„ ๋“ฑ๋กํ•ด๋„ OCP / DIP ์ง€ํ‚ฌ ์ˆ˜ ์žˆ์Œ
 
์ˆ˜๋™๋นˆ ๋“ฑ๋ก์€ ์–ธ์ œ ์‚ฌ์šฉ?
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ํฌ๊ฒŒ ์—…๋ฌด ๋กœ์ง๊ณผ ๊ธฐ์ˆ  ์ง€์› ๋กœ์ง์œผ๋กœ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ๋‹ค.

์—…๋ฌด ๋กœ์ง ๋นˆ
: ์›น์„ ์ง€์›ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ, ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์ด ์žˆ๋Š” ์„œ๋น„์Šค, ๋ฐ์ดํ„ฐ ๊ณ„์ธต์˜ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋“ฑ์ด ๋ชจ๋‘ ์—…๋ฌด ๋กœ์ง์ด๋‹ค. ๋ณดํ†ต ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ฐœ๋ฐœํ•  ๋•Œ ์ถ”๊ฐ€๋˜๊ฑฐ๋‚˜ ๋ณ€๊ฒฝ๋œ๋‹ค. (DAO ๊ฐ™์€)

๊ธฐ์ˆ  ์ง€์› ๋นˆ
: ๊ธฐ์ˆ ์ ์ธ ๋ฌธ์ œ๋‚˜ ๊ณตํ†ต ๊ด€์‹ฌ์‚ฌ(AOP)๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‚˜, ๊ณตํ†ต ๋กœ๊ทธ ์ฒ˜๋ฆฌ ์ฒ˜๋Ÿผ ์—…๋ฌด ๋กœ์ง์„ ์ง€์›ํ•˜๊ธฐ ์œ„ํ•œ ํ•˜๋ถ€ ๊ธฐ์ˆ ์ด๋‚˜ ๊ณตํ†ต ๊ธฐ์ˆ ๋“ค์ด๋‹ค.

์—…๋ฌด ๋กœ์ง์€ ์ˆซ์ž๋„ ๋งค์šฐ ๋งŽ๊ณ , ํ•œ๋ฒˆ ๊ฐœ๋ฐœํ•ด์•ผ ํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ, ์„œ๋น„์Šค, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ฒ˜๋Ÿผ ์–ด๋Š์ •๋„ ์œ ์‚ฌํ•œ ํŒจํ„ด์ด ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ์ž๋™ ๊ธฐ๋Šฅ์„ ์ ๊ทน ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋ณดํ†ต ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ด๋„ ์–ด๋–ค ๊ณณ์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ํŒŒ์•…ํ•˜๊ธฐ ์‰ฝ๋‹ค.

๊ธฐ์ˆ  ์ง€์› ๋กœ์ง์€ ์—…๋ฌด ๋กœ์ง๊ณผ ๋น„๊ตํ•ด์„œ ๊ทธ ์ˆ˜๊ฐ€ ๋งค์šฐ ์ ๊ณ , ๋ณดํ†ต ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ „๋ฐ˜์— ๊ฑธ์ณ์„œ ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—…๋ฌด ๋กœ์ง์€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์–ด๋””๊ฐ€ ๋ฌธ์ œ์ธ์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ์ž˜ ๋“œ๋Ÿฌ๋‚˜์ง€๋งŒ, ๊ธฐ์ˆ  ์ง€์› ๋กœ์ง์€ ์ ์šฉ์ด ์ž˜ ๋˜๊ณ  ์žˆ๋Š”์ง€ ์•„๋‹Œ์ง€ ์กฐ์ฐจ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ๊ธฐ์ˆ  ์ง€์› ๋กœ์ง๋“ค์€ ๊ฐ€๊ธ‰์  ์ˆ˜๋™ ๋นˆ ๋“ฑ๋ก์„ ์‚ฌ์šฉํ•ด์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๊ด‘๋ฒ”์œ„ํ•˜๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š” ๊ธฐ์ˆ  ์ง€์› ๊ฐ์ฒด๋Š” ์ˆ˜๋™ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•ด์„œ ๋”ฑ! ์„ค์ • ์ •๋ณด์— ๋ฐ”๋กœ ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์œ ์ง€๋ณด์ˆ˜ ํ•˜๊ธฐ ์ข‹๋‹ค.

 

๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ค‘์—์„œ ๋‹คํ˜•์„ฑ์„ ์ ๊ทน ํ™œ์šฉํ•  ๋•Œ

์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…
- ์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•  ๋•Œ, List, Map์„ ๋‹ค์‹œ ๋ณด์ž.
DiscountService ๊ฐ€ ์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…์œผ๋กœ Map<String, DiscountPolicy> ์— ์ฃผ์ž…์„ ๋ฐ›๋Š” ์ƒํ™ฉ์„ ์ƒ๊ฐํ•ด๋ณด์ž.
์—ฌ๊ธฐ์— ์–ด๋–ค ๋นˆ๋“ค์ด ์ฃผ์ž…๋  ์ง€, ๊ฐ ๋นˆ๋“ค์˜ ์ด๋ฆ„์€ ๋ฌด์—‡์ผ์ง€ ์ฝ”๋“œ๋งŒ ๋ณด๊ณ  ํ•œ๋ฒˆ์— ์‰ฝ๊ฒŒ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์„๊นŒ?
์ž๋™ ๋“ฑ๋ก์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํŒŒ์•…ํ•˜๋ ค๋ฉด ์—ฌ๋Ÿฌ ์ฝ”๋“œ๋ฅผ ์ฐพ์•„๋ด์•ผ ํ•œ๋‹ค.


์ด๋Ÿฐ ๊ฒฝ์šฐ ์ˆ˜๋™ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜ ๋˜๋Š” ์ž๋™์œผ๋กœํ•˜๋ฉด
ํŠน์ • ํŒจํ‚ค์ง€์— ๊ฐ™์ด ๋ฌถ์–ด๋‘๋Š”๊ฒŒ ์ข‹๋‹ค!
ํ•ต์‹ฌ์€ ๋”ฑ ๋ณด๊ณ  ์ดํ•ด๊ฐ€ ๋˜์–ด์•ผ ํ•œ๋‹ค!

์ด ๋ถ€๋ถ„์„ ๋ณ„๋„์˜ ์„ค์ • ์ •๋ณด๋กœ ๋งŒ๋“ค๊ณ  ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

@Configuration
  public class DiscountPolicyConfig {
      @Bean
      public DiscountPolicy rateDiscountPolicy() {
          return new RateDiscountPolicy();
      }
      @Bean
      public DiscountPolicy fixDiscountPolicy() {
          return new FixDiscountPolicy();
      }
}

 

์ด ์„ค์ • ์ •๋ณด๋งŒ ๋ด๋„ ํ•œ๋ˆˆ์— ๋นˆ์˜ ์ด๋ฆ„์€ ๋ฌผ๋ก ์ด๊ณ , ์–ด๋–ค ๋นˆ๋“ค์ด ์ฃผ์ž…๋ ์ง€ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๋ž˜๋„ ๋นˆ ์ž๋™ ๋“ฑ๋ก์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์œผ๋ฉด ํŒŒ์•…ํ•˜๊ธฐ ์ข‹๊ฒŒ DiscountPolicy ์˜ ๊ตฌํ˜„ ๋นˆ๋“ค๋งŒ ๋”ฐ๋กœ ๋ชจ์•„์„œ ํŠน์ • ํŒจํ‚ค์ง€์— ๋ชจ์•„๋‘์ž.

 

์ฐธ๊ณ ๋กœ ์Šคํ”„๋ง๊ณผ ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š” ์ˆ˜ ๋งŽ์€ ๋นˆ๋“ค์€ ์˜ˆ์™ธ๋‹ค. 
์ด๋Ÿฐ ๋ถ€๋ถ„๋“ค์€ ์Šคํ”„๋ง ์ž์ฒด๋ฅผ ์ž˜ ์ดํ•ดํ•˜๊ณ  ์Šคํ”„๋ง์˜ ์˜๋„๋Œ€๋กœ ์ž˜ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ค‘์š”ํ•˜๋‹ค. 
์Šคํ”„๋ง ๋ถ€ํŠธ์˜ ๊ฒฝ์šฐ DataSource ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์— ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ์ˆ  ์ง€์› ๋กœ์ง๊นŒ์ง€ ๋‚ด๋ถ€์—์„œ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๋Š”๋ฐ, ์ด๋Ÿฐ ๋ถ€๋ถ„์€ ๋ฉ”๋‰ด์–ผ์„ ์ž˜ ์ฐธ๊ณ ํ•ด์„œ ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์˜๋„ํ•œ ๋Œ€๋กœ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค. 
๋ฐ˜๋ฉด์— ์Šคํ”„๋ง ๋ถ€ํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ ์ง์ ‘ ๊ธฐ์ˆ  ์ง€์› ๊ฐ์ฒด๋ฅผ ์Šคํ”„๋ง ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•œ๋‹ค๋ฉด ์ˆ˜๋™์œผ๋กœ ๋“ฑ๋กํ•ด์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ๋“œ๋Ÿฌ๋‚ด๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์ •๋ฆฌ

ํŽธ๋ฆฌํ•œ ์ž๋™ ๊ธฐ๋Šฅ์„ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜์ž
์ง์ ‘ ๋“ฑ๋กํ•˜๋Š” ๊ธฐ์ˆ  ์ง€์› ๊ฐ์ฒด๋Š” ์ˆ˜๋™ ๋“ฑ๋ก
๋‹คํ˜•์„ฑ์„ ์ ๊ทน ํ™œ์šฉํ•˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์€ ์ˆ˜๋™ ๋“ฑ๋ก์„ ๊ณ ๋ฏผํ•ด๋ณด์ž

 

  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ