의존관계 자동 주입은 스프링 컨테이너가 관리하는 컨테이너(스프링 빈)여야 동작한다.
스프링 빈이 아닌 일단 클래스에가서 암만@Autowired
갖다 박아봐야 아무일도 일어나지 않는다.
@Autowired
) 의존 관계를 주입 받는 방법이다.@ComponentScan
(boot에서는 @SpringBootApplication
)이 실행되면서 @Component
를 만나면 이제 빈으로 등록하기 위해서 생성자를 호출하는데 이때 @Autowired
를 만나면 스프링 컨테이너에서 생성되어있는 memberRepository 와 discountPolicy 빈을 꺼내와서 저기에 넣어준다.
이때 위 코드에서는 빠졌는데 private 다음에 final을 넣어주어서 프로젝트가 뜰 때 웬만하면 값을 항상 갖고 있도록 하는 것이 좋을 것이다.
이때 생성자가 1개밖에 없다면 @Autowired
를 생략할 수 있다.
스프링 빈이 등록될 때 한 큐에 일어난다.
- 특징
- 생성자 호출 시전에 딱 1번만 호출되는 것이 보장된다.
- 따라서 "불변, 필수" 의존관계에 사용
- 주로 생성자 주입을 사용한다.
@Component
public class OrderServiceImpl implements OrderService {
// private final MemberRepository memberRepository = new MemoryMemberRepository();
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
// private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
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
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
이렇게 setting 함수에 @Autowired
를 붙여도 된다.
앞서 스프링 빈이 등록된 다음 -> 스프링 빈 의존관계 설정 (준비) -> 스프링 빈 의존관계 설정 (완료) 이렇게 나뒤어있다고 말했다.
이를 이렇게 따로 나눴던 이유는 바로 setter 주입에 있다. 바로 이 스프링 빈 의존관계 설정을 할 때 일어난 것이다.
그리고 setting 메서드가 DI를 해주기 때문에 따로 생성자 함수가 필요없어진다.
그럼 생성자주입과 setter 주입의 차이는 1. 주입시점, 2. 값의 수정가능 여부 정도가 있겠다.
- 특징
- 선택, 변경 가능성이 있는 의존관계에 사용
- 자바 bean property 규약의 수정자 메서드 방식을 사용하는 방법이다.
앞서 선택, 변경 가능이 있다고 했는데 @Autowired
의 기본 동작은 주입할 대상이 없으면 오류가 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false)
로 지정하면 된다.
앞서 "자바 빈 프로퍼티 규약" 이라고 했는데 이는 필드의 값을 직접변경하는 것이 아닌, getter, setter 메서드를 통해 값을 수정하는 규칙을 뜻한다.
상남자 스럽긴 한데 앞서 말했던 "자바 빈 프로퍼티 규약"을 어기는 방법이다. 바로 플드에 바로 때려박는 것이다. 이는 코드를 매우 심플하게 짤 수 있다. 뭐 생성자고 setter고 다 필요없이 그냥 필드 private 앞에 @Autowired
를 박으면 된다.
하지만 상남자들은 오래살지 못 한다. 필드 주입 역시 예전에 쓰던 방식이고 권장하지 않는 방법이다.
특징
@Configuration
같은 곳에서만 특별한 용도로 사용// 생성자 함수
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
// 반환 타입만 추가한 아무 함수
@Autowired
public void somethingMethod(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}