๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
  1. ์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…
    1. 1. ๋‹ค์–‘ํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ๋ฐฉ๋ฒ•
      1. 1. ์ƒ์„ฑ์ž ์ฃผ์ž…
      2. 2. ์ˆ˜์ •์ž ์ฃผ์ž…(Setter ์ฃผ์ž…)
      3. 3. ํ•„๋“œ ์ฃผ์ž…
      4. 4.์ผ๋ฐ˜ ๋ฉ”์„œ๋“œ ์ฃผ์ž…
    2. 2. ์˜ต์…˜์ฒ˜๋ฆฌ
    3. 3. ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํƒํ•˜๋ผ
      1. ๋ถˆ๋ณ€
      2. ๋ˆ„๋ฝ**
      3. final
    4. 4. ๋กฌ๋ณต๊ณผ ์ตœ์‹  ํŠธ๋ Œ๋“œ
      1. ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐฉ๋ฒ•
      2. ๋กฌ๋ณต์„ ํ™œ์šฉํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…
    5. 5. ์กฐํšŒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ
      1. ์˜ˆ์‹œ
    6. 6. @Autowired ํ•„๋“œ ๋ช…, @Qualifier, @Primary
      1. 1. @Autowired ํ•„๋“œ ๋ช… ๋งค์นญ
      2. 2. @Qualifier ์‚ฌ์šฉ
      3. 3. @Primary ์‚ฌ์šฉ
      4. Primary vs Qualifier
    7. 7. Annotation ์ง์ ‘ ๋งŒ๋“ค๊ธฐ
      1. annotation ์ ์šฉ
    8. 8. List, Map : ์กฐํšŒํ•œ ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•  ๋•Œ
      1. ์˜ˆ์‹œ ์ฝ”๋“œ
    9. 9. ์ž๋™, ์ˆ˜๋™์˜ ์˜ฌ๋ฐ”๋ฅธ ์‹ค๋ฌด ์šด์˜ ๊ธฐ์ค€
      1. ๊ธฐ๋ณธ์œผ๋กœ๋Š” ํŽธ๋ฆฌํ•œ ์ž๋™ ๊ธฐ๋Šฅ ์‚ฌ์šฉ
      2. ์ˆ˜๋™ ๋นˆ ๋“ฑ๋ก์€ ๋กœ์ง์— ๋”ฐ๋ผ ์‚ฌ์šฉ
      3. ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ์ค‘์—์„œ ๋‹คํ˜•์„ฑ์„ ์ ๊ทน ํ™œ์šฉํ•  ๋•Œ
โญ Personal_Study/Spring

์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…

by ํฌ์ŠคํŠธ์‰์ดํฌ 2023. 1. 9.

์˜์กด๊ด€๊ณ„ ์ž๋™ ์ฃผ์ž…

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

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

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

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

โœ” ๋ถˆ๋ณ€, ํ•„์ˆ˜ ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ

// OrderServiceImpl.java

@Component
public class OrderServiceImpl implements OrderService{

//    final -> ๋ฐ˜๋“œ์‹œ ๊ฐ’์„ ํ• ๋‹นํ•ด์ค˜์•ผํ•œ๋‹ค.(ํ•„์ˆ˜, ๋ถˆ๋ณ€)
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;


    @Autowired // ์ƒ์„ฑ์ž๊ฐ€ ํ•œ ๊ฐœ๋งŒ ์žˆ์„ ๊ฒฝ์šฐ ์ƒ๋žตํ•ด๋„ ๋œ๋‹ค.
    public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy  DiscountPolicy discountPolicy) {
//        System.out.println("memberRepository = " + memberRepository);
//        System.out.println("discountPolicy = " + discountPolicy);
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
    ...
}

์ƒ์„ฑ์ž๊ฐ€ ํ•œ ๊ฐœ๋งŒ ์žˆ์„ ๊ฒฝ์šฐ `@Autowired ์ƒ๋žต ๊ฐ€๋Šฅ

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

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

์„ ํƒ, ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์˜์กด๊ด€๊ณ„์— ์‚ฌ์šฉ
์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ์˜ ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์‚ฌ์šฉ

// OrderServiceImpl.java

@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;
    }
    ...
}

โ€ป ์ž๋ฐ”๋นˆ ํ”„๋กœํผํ‹ฐ ๊ทœ์•ฝ: ํ•„๋“œ์˜ ๊ฐ’์„ ์ง์ ‘ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๊ณ  setter๋ž‘ getter ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•ด ๊ฐ’์„ ์ฝ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ๊ทœ์น™

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

์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๊ฐ„๊ฒฐํ•˜๋‚˜ ์™ธ๋ถ€์—์„œ ๋ณ€๊ฒฝ์ด ๋ถˆ๊ฐ€๋Šฅํ•ด ํ…Œ์ŠคํŠธํ•˜๊ธฐ ํž˜๋“ค๋‹ค!

๊ฐ€๊ธ‰์  ์‚ฌ์šฉ ์ž์ œ!!

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

// OrederServiceImpl.java

@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MemberRepository memberRepository;
    @Autowired
    private DiscountPolicy 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;
    }

}

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

์ฃผ์ž…ํ•  ์Šคํ”„๋ง ๋นˆ์ด ์—†์–ด๋„ ๋ฉ”์„œ๋“œ๋ฅผ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ ์˜ต์…˜ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผํ•œ๋‹ค.

์˜ต์…˜ ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•

  • @Autowired(required=false) : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด ์ˆ˜์ •์ž ๋ฉ”์„œ๋“œ ์ž์ฒด๊ฐ€ ํ˜ธ์ถœ ์•ˆ๋จ
  • org.springframework.lang.@Nullable : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด null์ด ์ž…๋ ฅ๋œ๋‹ค.
  • Optional<> : ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ์—†์œผ๋ฉด Optional.empty ๊ฐ€ ์ž…๋ ฅ๋œ๋‹ค
// AutowiredTest.java

public class AutowiredTest {

    @Test
    void AutowiredOption() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
    }

    static class TestBean {

        // ์Šคํ”„๋ง ๋นˆ์— ๋“ฑ๋ก๋˜์ง€ ์•Š์€ ๋Œ€์ƒ ์ฃผ์ž…ํ•ด๋ณด๊ธฐ (Member)

        // 1. ์˜์กด ๊ด€๊ณ„๊ฐ€ ์—†์œผ๋ฉด ์•„์˜ˆ ํ˜ธ์ถœ์ด ์•ˆ๋œ๋‹ค
        @Autowired(required = false)
        public void setNoBean1(Member noBean1) {
            System.out.println("noBean1 = " + noBean1);
        }

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

        // 3. Optional.empty ํ˜ธ์ถœ
        @Autowired
        public void setNoBean3(Optional<Member> noBean3) {
            System.out.println("noBean3 = " + noBean3);
        }
    }
}
// ํ…Œ์ŠคํŠธ ๊ฒฐ๊ณผ

// 1. ์€ ํ˜ธ์ถœ์ด ์•ˆ๋œ๋‹ค
noBean2 = null
noBean3 = Optional.empty

3. ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ์„ ํƒํ•˜๋ผ

์ตœ๊ทผ์—๋Š” ์ƒ์„ฑ์ž ์ฃผ์ž…์ด ๊ถŒ์žฅ๋œ๋‹ค

๋ถˆ๋ณ€

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

์ˆ˜์ •์ž ์ฃผ์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด setter ๋ฉ”์„œ๋“œ๋ฅผ public์œผ๋กœ ์—ด์—ฌ๋‘์–ด์•ผ ํ•œ๋‹ค

  • ๋ˆ„๊ตฐ๊ฐ€ ์‹ค์ˆ˜๋กœ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ
  • ๋ณ€๊ฒฝ ์•ˆ๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์—ด์–ด๋‘๋Š” ๊ฒƒ์€ ์ง€์–‘

์ƒ์„ฑ์ž ์ฃผ์ž…์€ ๊ฐ์ฒด ์ƒ์„ฑ ์‹œ์—๋งŒ 1๋ฒˆ ํ˜ธ์ถœ๋˜๊ณ  ์ดํ›„์— ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค -> ๋ถˆ๋ณ€ ์„ค๊ณ„

๋ˆ„๋ฝ**

ํ”„๋ ˆ์ž„์›Œํฌ ์—†์ด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ์ฝ”๋“œ ๋‹จ์œ„๋กœ ์‹คํ–‰ ์‹œ(@Autowired ๋™์ž‘ x)

  • ์ˆ˜์ •์ž ์ฃผ์ž…์—์„œ๋Š” ์‹คํ–‰์€ ๋˜๋‚˜ NPE๋ฐœ์ƒ
  • ์ƒ์„ฑ์ž ๋ฉ”์„œ๋“œ์—์„œ๋Š” ์ปดํŒŒ์ผ ์˜ค๋ฅ˜ ๋ฐœ์ƒ -> ๋””๋ฒ„๊น… ์šฉ์ด

final

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

์˜ˆ์‹œ ์ฝ”๋“œ

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    // discountPolicy ๋ˆ„๋ฝ
    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
    }
 //...
}

์ปดํŒŒ์ผ ์˜ค๋ฅ˜: java: variable discountPolicy might not have been initialized

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

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

๋งค๋ฒˆ ์ƒ์„ฑ์ž ์ฃผ์ž… ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ ๋ฒˆ๊ฑฐ๋กญ๋‹ค! -> ๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™œ์šฉ

๋กฌ๋ณต ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐฉ๋ฒ•

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.7.7'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
    mavenCentral()
}

//lombok ์„ค์ • ์ถ”๊ฐ€ ์‹œ์ž‘
configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}
//lombok ์„ค์ • ์ถ”๊ฐ€ ๋

dependencies {

    //lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ์‹œ์ž‘
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testCompileOnly 'org.projectlombok:lombok'
    testAnnotationProcessor 'org.projectlombok:lombok'
    //lombok ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ถ”๊ฐ€ ๋

    implementation 'org.springframework.boot:spring-boot-starter'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'

}

tasks.named('test') {
    useJUnitPlatform()
}
  1. Preferences(์œˆ๋„์šฐ File Settings) plugin lombok ๊ฒ€์ƒ‰ ์„ค์น˜ ์‹คํ–‰ (์žฌ์‹œ์ž‘)
  2. Preferences Annotation Processors ๊ฒ€์ƒ‰ Enable annotation processing ์ฒดํฌ (์žฌ์‹œ์ž‘)
  3. ์ž„์˜์˜ ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  @Getter, @Setter ํ™•์ธ

๋กฌ๋ณต์„ ํ™œ์šฉํ•œ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž…

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

// OrderServiceImpl.java

@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;
    }
}

๋กฌ๋ณต ์ ์šฉ

// OrderServiceImpl.java

@Component
@RequiredArgsConstructor // final์ด ๋ถ™์€ ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด ์ค€๋‹ค
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    ...
}

โœ” @RequiredArgsConstructor : final์ด ๋ถ™์€ ํ•„๋“œ๋ฅผ ๋ชจ์•„์„œ ์ƒ์„ฑ์ž๋ฅผ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค€๋‹ค

์ตœ๊ทผ์—๋Š” ์ƒ์„ฑ์ž๋ฅผ 1๊ฐœ ๋‘๊ณ  @Autowired๋ฅผ ์ƒ๋žตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด์„œ, Lombok๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ @RequiredArgsConstructor๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•œ๋‹ค

5. ์กฐํšŒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ

@Autowired๋Š” ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ๋‹ค (ac.getBean(DiscountPolicy.class)์™€ ์œ ์‚ฌ) -> ๊ฐ™์€ ํƒ€์ž…์˜ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ด๋ฉด ๋ฌธ์ œ ๋ฐœ์ƒ!

์˜ˆ์‹œ

// FixDiscountPolicy.java

@Component
public class FixDiscountPolicy implements DiscountPolicy {}
// RateDiscountPolicy.java

@Component
public class RateDiscountPolicy implements DiscountPolicy {}
// ์˜์กด๊ด€๊ฒŒ ์ž๋™ ์ฃผ์ž… ์‹คํ–‰

@Autowired
private DiscountPolicy discountPolicy
NoUniqueBeanDefinitionException: No qualifying bean of type 
'hello.core.discount.DiscountPolicy' available: 
expected single matching bean but found 2: fixDiscountPolicy,rateDiscountPolicy

NoUniqueBeanDefinitionException ์˜ค๋ฅ˜ ๋ฐœ์ƒ

๊ทธ๋ ‡๋‹ค๊ณ  ํ•˜์œ„ ํƒ€์ž…์œผ๋กœ ์ง€์ •ํ•˜๋ฉด DIP ์œ„๋ฐฐ ๋ฐ ์œ ์—ฐ์„ฑ ๊ฐ์†Œ! ๊ทธ๋ฆฌ๊ณ  ํ•˜์œ„ ํƒ€์ž…๋„ ๊ฐ™์œผ๋ฉด ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ

๊ทธ๋ ‡๋‹ค๋ฉด...?

6. @Autowired ํ•„๋“œ ๋ช…, @Qualifier, @Primary

์กฐํšŒ ๋Œ€์ƒ ๋นˆ์ด 2๊ฐœ ์ด์ƒ์ผ ๋•Œ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

  1. @Autowired ํ•„๋“œ ๋ช… ๋งค์นญ
  2. @Qualifier -> @Qualifier๋ผ๋ฆฌ ๋งค์นญ -> ๋นˆ ์ด๋ฆ„ ๋งค์นญ
  3. @Primary ์‚ฌ์šฉ

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

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

@Autowired
// ๊ธฐ์กด ์ฝ”๋“œ
// private DiscountPolicy discountPolicy
// ํ•„๋“œ ๋ช…์„ ๋นˆ ์ด๋ฆ„์œผ๋กœ ๋ณ€๊ฒฝ
private DiscountPolicy rateDiscountPolicy 

2. @Qualifier ์‚ฌ์šฉ

โœ” @Qualifier๋ฅผ ํ†ตํ•ด ์ถ”๊ฐ€๊ตฌ๋ถ„์ž๋ฅผ ๋ถ™์—ฌ์ค€๋‹ค (๋นˆ ์ด๋ฆ„ ๋ณ€๊ฒฝ x)

๋นˆ ๋“ฑ๋ก์‹œ @Qualifier ๋ถ™์—ฌ์ฃผ๊ธฐ


// RateDiscountPolicy.java
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}

// FixDiscountPolicy.java
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}

์ฃผ์ž…์‹œ์— @Qualifier๋ฅผ ๋ถ™์—ฌ์ฃผ๊ณ  ๋“ฑ๋กํ•œ ์ด๋ฆ„์„ ์ ์–ด์ฃผ๊ธฐ

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

ํ•ด๋‹น qualifier๋ฅผ ๋ชป ์ฐพ์œผ๋ฉด ๋‹ค์‹œ ๋นˆ ์ด๋ฆ„์œผ๋กœ ๋งค์นญ์„ ํ•˜์ง€๋งŒ qulifier๋Š” ๊ฐ€๊ธ‰์  qualifier๋ผ๋ฆฌ ๋งค์นญํ•˜๋Š” ๊ฒƒ ๊ถŒ์žฅ!

3. @Primary ์‚ฌ์šฉ

โœ” @Primary: ์šฐ์„ ์ˆœ์œ„ ์ง€์ •

  • @Autowired ์‹œ์— ์—ฌ๋Ÿฌ ๋นˆ์ด ๋งค์นญ๋˜๋ฉด @Primary ๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง„๋‹ค
// rateDiscountPolicy ๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง„๋‹ค

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}

@Component
public class FixDiscountPolicy implements DiscountPolicy {}

Primary vs Qualifier

@Qualifier ์˜ ๋‹จ์ ์€ ์ฃผ์ž… ๋ฐ›์„ ๋•Œ ๋ชจ๋“  ์ฝ”๋“œ์— @Qualifier๋ฅผ ๋ถ™์—ฌ์ค˜์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ

๋ฉ”์ธ ์ปค๋„ฅ์…˜์€ @Primary๋ฅผ ํ™œ์šฉํ•ด @Qualifier ์ง€์ • ์—†์ด ํŽธํ•˜๊ฒŒ ์กฐํšŒ

์„œ๋ธŒ ์ปค๋„ฅ์…˜์€ @Qualifier๋ฅผ ์ง€์ •ํ•ด ๋ช…์‹œ์ ์œผ๋กœ ์ปค๋„ฅ์…˜ ๋นˆ ํš๋“

์šฐ์„ ์ˆœ์œ„

์ข์€ ๋ฒ”์œ„์˜ @Qualifier๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ€์ง„๋‹ค

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

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

์• ๋…ธํ…Œ์ด์…˜์„ ๋งŒ๋“ค์–ด์„œ ๋ฌธ์ œ ํ•ด๊ฒฐ

package hello.core.annotation;

import org.springframework.beans.factory.annotation.Qualifier;

import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}

annotation ์ ์šฉ

@Component
@MainDiscountPolicy
public class RateDiscountPolicy implements DiscountPolicy {}
// OrderServiceImpl.java

//์ƒ์„ฑ์ž ์ž๋™ ์ฃผ์ž…
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

annotation์—๋Š” ์ƒ์† ๊ธฐ๋Šฅ์ด ์—†๋‹ค

์œ„์™€ ๊ฐ™์ด ์—ฌ๋Ÿฌ anntotation์„ ๋ชจ์•„์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์€ java๊ฐ€ ์•„๋‹ˆ๋ผ ์Šคํ”„๋ง์—์„œ ์ง€์›ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ

๋‹ค๋ฅธ annotation๋„ ์กฐํ•ฉ / ์žฌ์ •์˜ํ•  ์ˆ˜ ์žˆ์œผ๋‚˜ ๊ฐ€๊ธ‰์  ์ง€์–‘

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

โœ” ์˜๋„์ ์œผ๋กœ ํ•ด๋‹น ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด ๋ชจ๋‘ ํ•„์š”ํ•œ ๊ฒฝ์šฐ -> List, Map ํ™œ์šฉํ•ด ์ „๋žตํŒจํ„ด ๊ตฌํ˜„

ex) ํ• ์ธ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š”๋ฐ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ง์ ‘ ํ• ์ธ์˜ ์ข…๋ฅ˜(rate, fix) ์„ ํƒ ๊ฐ€๋Šฅ

์˜ˆ์‹œ ์ฝ”๋“œ


package hello.core.autowired;

import hello.core.AutoAppConfig;
import hello.core.discount.DiscountPolicy;
import hello.core.member.Grade;
import hello.core.member.Member;
import hello.core.scan.AutoAppConfigTest;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;

public class allBeanTest {

    @Test
    void findAllBean() {
        AnnotationConfigApplicationContext 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");

        Assertions.assertThat(discountService).isInstanceOf(DiscountService.class);
        Assertions.assertThat(discountPrice).isEqualTo(1000);

        int rateDiscountPrice = discountService.discount(member, 20000, "rateDiscountPolicy");
        Assertions.assertThat(rateDiscountPrice).isEqualTo(2000);


    }

    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);
            return discountPolicy.discount(member, price);
        }
    }
}

๋กœ์ง

DiscountService๋Š” Map์œผ๋กœ ๋ชจ๋“  DiscoutPolicy ์ฃผ์ž… ๋ฐ›๋Š”๋‹ค (fixDiscountPolicy & rateDiscountPolicy)

๋ฉ”์„œ๋“œ discount()๋Š” doscountCode๋กœ ๋„˜์–ด์˜จ discountPolicy์— ๋งž๋Š” ์Šคํ”„๋ง ๋นˆ์„ ์ฐพ์•„์„œ ์‹คํ–‰ํ•œ๋‹ค

์ฃผ์ž…

Map<String, DiscountPolicy> : ํ‚ค์— ์Šคํ”„๋ง ๋นˆ์˜ ์ด๋ฆ„์„, ๊ฐ’์œผ๋กœ DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„ ๋‹ด์•„์ค€๋‹ค.

List<DiscountPolicy> : DiscountPolicy ํƒ€์ž…์œผ๋กœ ์กฐํšŒํ•œ ๋ชจ๋“  ์Šคํ”„๋ง ๋นˆ์„ ๋‹ด์•„์ค€๋‹ค.

๋งŒ์•ฝ ํ•ด๋‹นํ•˜๋Š” ํƒ€์ž…์˜ ์Šคํ”„๋ง ๋นˆ์ด ์—†์œผ๋ฉด, ๋นˆ ์ปฌ๋ ‰์…˜์ด๋‚˜ Map์„ ์ฃผ์ž…

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

๊ธฐ๋ณธ์œผ๋กœ๋Š” ํŽธ๋ฆฌํ•œ ์ž๋™ ๊ธฐ๋Šฅ ์‚ฌ์šฉ

์Šคํ”„๋ง์ด ๋‚˜์˜ค๊ณ  ์‹œ๊ฐ„์ด ์ง€๋‚  ์ˆ˜๋ก ์ž๋™ ์„ ํ˜ธ ์ถ”์„ธ

@Component ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ @Controller, @Service , @Repository ์ฒ˜๋Ÿผ ๊ณ„์ธต์— ๋งž์ถ”์–ด ์ผ๋ฐ˜์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ์ง์„ ์ž๋™์œผ๋กœ ์Šค์บ”ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›

์Šคํ”„๋ง๋ถ€ํŠธ๋Š” ์ปดํฌ๋„ŒํŠธ ์Šค์บ”์„ ๊ธฐ๋ณธ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๋‹ค๋ฅธ ์Šคํ”„๋ง ๋นˆ๋“ค๋„ ์กฐ๊ฑด์ด ๋งž์œผ๋ฉด ์ž๋™์œผ๋กœ ๋™๋ฅต๋˜๋„๋ก ์„ค๊ณ„

์ˆ˜๋™ ๋นˆ ๋“ฑ๋ก์€ ๋กœ์ง์— ๋”ฐ๋ผ ์‚ฌ์šฉ

โœ” ์—…๋ฌด ๋กœ์ง ๋นˆ

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

โœ” ๊ธฐ์ˆ  ์ง€์› ๋นˆ

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

์—…๋ฌด ๋กœ์ง์€ ์ˆซ์ž๋„ ๋งค์šฐ ๋งŽ๊ณ  ํ•œ๋ฒˆ ๊ฐœ๋ฐœํ•˜๋ฉด ์ปจํŠธ๋กค๋Ÿฌ, ์„œ๋น„์Šค, ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋“ฑ ์œ ์‚ฌํ•œ ํŒจํ„ด ์กด์žฌ
-> ์ž๋™ ๊ธฐ๋Šฅ ์‚ฌ์šฉ

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

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

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

์œ„์˜ List, Map๊ณผ ๊ฐ™์ด ๋‹คํ˜•์„ฑ์„ ์ ๊ทน ํ™œ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ํ˜‘์—… ์‹œ์— ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ํŒŒ์•…ํ•˜๊ธฐ ์–ด๋ ต๋‹ค

โœ” ์ˆ˜๋™ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜๊ฑฐ๋‚˜ ์ž๋™์œผ๋กœ ํ•˜๋ฉด ํŠน์ • ํŒจํ‚ค์ง€์— ๊ฐ™์ด ๋ฌถ์–ด๋‘๊ธฐ

์˜ˆ์‹œ ์ฝ”๋“œ

@Configuration
public class DiscountPolicyConfig {

    @Bean
    public DiscountPolicy rateDiscountPolicy() {
        return new RateDiscountPolicy();
    }

    @Bean
    public DiscountPolicy fixDiscountPolicy() {
        return new FixDiscountPolicy();
    }
}

์„ค์ • ์ •๋ณด์™€ ์˜์กด๊ด€๊ณ„ ์ฃผ์ž… ์ •๋ณด๊ฐ€ ํ•œ ๋ˆˆ์— ํŒŒ์•…๋œ๋‹ค

๋Œ“๊ธ€