생성자 주입
수정자 주입(setter 활용)
필드 주입
일반 메서드 주입
@Component
public class MemoryMemberRepository implements MemberRepository{
@Autowired
private static Map<Long, Member> store = new HashMap<>(); //Map, id랑 Member 객체 간이적으로 메모리에 저장
@Override
public void save(Member member) {
store.put(member.getId(), member);
}
@Override
public Member findById(Long memberId) {
return store.get(memberId);
}
}
이렇게 생성자 주입해줌.
@Autowired
자동으로, 한번만 생성해주는게 보장됨.
그래서 보통 불변, 필수인 의존관계에 씀.
딱 생성자를 통해서만 의존관계가 주입되고, 어느 누구도 필드를 수정할 수 없다.
그래서 이런 거에는 setter 안놔둠.
생성자가 하나일 때는 @Autowired 안해도 된다고 하던데 그래도 명시적으로 해두는 게 좋지 않나?
@Component
public class OrderServiceImpl implements OrderService{
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
@Autowired
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy){
this.discountPolicy = discountPolicy;
}
}
이런 식으로 setter에 @Autowired를 붙여 생성자 주입 가능.
setMem 이 이름 규칙때문에 알아서 찾는 듯.
그리고 setter 의존관계 주입하더라도, 결국 생성하려면 생성자를 호출해야 하기 때문에 @Autowired 없어도 생성자 알아서 호출 하는 듯.. 그 후에 setter 하는거임.
@Autowired는 주입할 대상이 없으면 오류가 발생하는데, 주입할 대상이 없어도 동작하도록 하려면 @Autowired(required = flase) 쓰면 됨
선택, 변경 가능성이 있을 때 이렇게 씀.
필드 주입
@Component
public class OrderServiceImpl implements OrderService{
@Autowired private MemberRepository memberRepository;
@Autowired private DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
private 인데도 넣어줌.
이건 안씀.
외부에서 변경이 불가능. 그래서 순수자바코드로 Test하기 어려움. 무조건 스프링 컨테이너 띄우고 거기서 bean을 가져와야 됨.
DI 프레임워크가 없으면 아무것도 못함.
일반 메서드 주입
@Autowired는 아무 메서드나 사용 가능.
@Component
public class OrderServiceImpl implements OrderService{
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Override
public Order createOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy){
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
한번에 여러 필드 주입가능
그러나 잘 쓰지 않음.. 굳이.. 생성자로 하면 되는데..
'스프링 > 1. 스프링 핵심 원리' 카테고리의 다른 글
35강. 생성자 주입을 사용하라. (0) | 2023.07.22 |
---|---|
34강. 의존관계 주입 옵션 (0) | 2023.07.22 |
32강. 충돌, 중복등록 (0) | 2023.07.21 |
31강. 필터 (0) | 2023.07.21 |
29강. 컴포넌트 스캔 (0) | 2023.07.20 |