Notice
Recent Posts
Recent Comments
Link
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 |
Tags
- import.meta.url
- 노드 내장 객체
- 이분탐색
- 프롬프트
- 프롬프트엔지니어링
- 이진탐색
- 우테코 프리코스
- 8기
- exports
- CommonJS
- HttpCookieOAuth2AuthorizationRequestRepository
- Console
- 다이내믹 임포트
- Global
- MAX_VALUE
- 프리코스
- nodejs
- __filename
- oAuth2
- 객체지향의 사실과 오해
- __dirname
- await
- 파라메트릭 서치
- 객체지향
- 안드로이드 스튜디오
- JPA
- 순환참조
- Async
- 백준
- 우테코
Archives
- Today
- Total
코딩하는 감쟈
스프링 핵심 개념원리6 본문
다양한 의존관계 주입 방법
생성자 주입
수정자 주입
필드 주입
일반 메서드 주입
1. 생성자 주입
@Autowired public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; }불변, 필수 의존관계에 사용
생성자가 한개뿐이라면 생략 가능
2. 수정자 주입
@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; } }선택, 변경 가능성이 있는 의존관계에서 사용
3. 필드 주입
@Component public class OrderServiceImpl implements OrderService { @Autowired private MemberRepository memberRepository; @Autowired private DiscountPolicy discountPolicy; }외부에서 변경이 불가능하다는 단점
DI 프레임워크가 없으면 아무것도 할 수 없다.
사용하지 말자
- 실제 코드와 상관없는 테스트 코드에서는 사용해도 괜찮다.
4. 일반 메서드 주입
@Autowired public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; }
- 실제 코드와 상관없는 테스트 코드에서는 사용해도 괜찮다.
거의 사용 안함
옵션 처리
@Autowired(required = false) public void setNoBean1(Member noBean1) { System.out.println("noBean1 = " + noBean1); }
@Autowired(required = false)
public void setNoBean2(@Nullable Member noBean2) {
System.out.println("noBean1 = " + noBean2);
}
@Autowired(required = false)
public void setNoBean3(Optional
System.out.println("noBean1 = " + noBean3);
}
### 생성자 주입을 선택해라!
- 대부분의 의존관계 주입은 한번 일어나면 끝날 때까지 의존관계를 변경할 일이 없다.
- 변경하면 안되는 메서드를 열어두는 것은 좋은 설계 방법이 아니다.
```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 orderService = new OrderServiceImpl(memberRepository, new FixDiscountPolicy()); // 컴파일 오류
- 수정자 주입과는 다르게 생성자 주입을 사용해서 테스트를 할때, 컴파일 오류가 발생한다. 따라서 IDE에서 어떤 값을 필수로 주입해야 하는지 알 수 있다.
- final 키워드
- 생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 그래서 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에서 막아준다.
롬복과 최신 트랜드
- 생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 그래서 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에서 막아준다.
- 이거 꼭 활성화해야함

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
@RequiredArgsConstructor를 사용하면, final이 붙은 필드를 모아 아래 생성자를 자동으로 만들어준다.public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; }조회 빈이 2개 이상 문제
DiscountPolicy에 빈이 두개 등록되어있어서 문제@Autowired public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = discountPolicy; }- 해결방법
- @Autowired 필드명 매칭
- @Qualifier -> @Qualifier끼리 매칭 -> 빈 이름 매칭
- @Primary 사용
1. @Autowired 필드명 매칭
@Autowired는 타입 매칭을 시도하고, 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.@Autowired public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) { this.memberRepository = memberRepository; this.discountPolicy = rateDiscountPolicy; }
- 이렇게
rateDiscountPolicy처럼 구체적인 필드 이름을 넣어주면 해결된다.2. @Qualifier 사용
- 추가 구분자를 붙여주는 방법이다. 주입 시, 추가적인 방법을 제공하는 것이지 빈 이름을 변경하는 것은 아니다.
@Component @Qualifier("mainDiscountPolicy") public class RateDiscountPolicy implements DiscountPolicy {}
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Qualifier("mainDiscountPolicy")를 못찾는다면,mainDiscountPolicy라는 이름의 스프링 빈 이름을 찾는다.3. @Primary 사용
우선순위를 정하는 방법이다.
@Autowired시에 여러 빈이 매칭되면@Primary가 우선권을 가진다.@Component @Primary public class RateDiscountPolicy implements DiscountPolicy {}조회한 빈이 모두 필요할 때, List, Map
의도적으로 해당 타입의 스프링 빈이 다 필요한 경우도 있다.
static class DiscountService { private final Map<String, DiscountPolicy> policyMap; private final List<DiscountPolicy> policys; @Autowired public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policys) { this.policyMap = policyMap; this.policys = policys; } public int discount(Member userA, int price, String discountCode) { DiscountPolicy discountPolicy = policyMap.get(discountCode); return discountPolicy.discount(userA, price); } }
'Back-End > spring' 카테고리의 다른 글
| 스프링 핵심 개념원리8 (0) | 2025.07.12 |
|---|---|
| 스프링 핵심 개념원리7 (1) | 2025.07.12 |
| 스프링 핵심 개념원리5 (0) | 2025.07.12 |
| 스프링 핵심 개념원리4 (1) | 2025.07.12 |
| 스프링 핵심 개념원리3 (1) | 2025.07.12 |