(인프런) 김영한님의 스프링 핵심 원리-기본편을 공부하고 리뷰한 글입니다.
1. 다양한 의존관계 주입 방법
<의존관계 주입 방법>
1) 생성자 주입 -> 가장 많이 사용
2) 수정자 주입(setter 주입)
3) 필드 주입
4) 일반 메서드 주입
1. 생성자 주입
생성자를 통해서 의존 관계를 주입받는 방법이다. (지금까지 우리가 진행했던 방법)
1) 특징
- 생성자 호출 시점에 딱 1번만 호출되는 것이 보장된다.
- 불변, 필수 의존관계에 사용
2) 생성자 주입 코드 작성
package hello.core.order;
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// 1. 생성자 주입
@Autowired // ac.getBean(MemberRepository.class), ac.getBean(DiscountPolicy.class)
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
...
}
3) @Autowired 생략
(중요!)생성자가 딱 1개있으면 @Autowired를 생략해도자동 주입된다. (스프링 빈에만 해당한다)
package hello.core.order;
@Component
public class OrderServiceImpl implements OrderService{
// 1. 생성자 주입
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
System.out.println("memberRepository = " + memberRepository);
System.out.println("discountPolicy = " + discountPolicy);
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
...
}
4) AutoAppConfigTest 실행 결과
@Autowired를 생략했지만 memberRepository, discountPolicy 에 자동으로 주입된 것을 확인할 수 있다.
2. 수정자 주입(setter 주입)
필드의 값을 변경하는 수정자 메서드(setter)를 통해 의존관계를 주입하는 방법이다.
1) 특징
- 선택, 변경 가능성이 있는 의존관계에 사용
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.
2) 수정자 주입 코드 작성
package hello.core.order;
@Component
public class OrderServiceImpl implements OrderService{
// setter를 만들기 위해 final 제거
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
// 2. 수정자 주입
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
System.out.println("memberRepository = " + memberRepository);
this.memberRepository = memberRepository;
}
// 2. 수정자 주입
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
System.out.println("discountPolicy = " + discountPolicy);
this.discountPolicy = discountPolicy;
}
...
}
(참고) @Autowired 의 기본 동작은 주입할 대상이 없으면 오류가 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false) 로 지정하면 된다.
e.g) memberRepository가 스프링 빈으로 등록되지 않아도 setmemberRepository() 를 호출할 수 있음
3) AutoAppConfigTest 실행 결과
setter 에 @Autowired를 붙였더니 memberRepository, discountPolicy 에 자동으로 주입된 것을 확인할 수 있다.
4) 자바빈 프로퍼티 규약 예시
자바에서 필드의 값을 직접 접근하지 않고, setXxx, GetXxx라는 메서드를 통해 값을 읽거나 수정하는 규칙이 있다. 이것이 바로 자바빈 프로퍼티 규약이다.
3. 필드 주입
필드에 바로 주입하는 방법이다. 특별한 경우(테스트 코드)를 제외하고 사용하지 말자!
1) 특징
- 코드가 간결하지만 외부에서 변경이 불가능해 테스트하기 힘들다는 치명적인 단점이 있다.
- DI 프레임워크가 없으면 아무것도 할 수 없다. (순수한 자바 코드로 테스트 할 수 X)
- 사용하지 않아야 하지만, 사용해도 되는 특수한 경우가 있다.
- 애플리케이션의 실제 코드와 관계 없는 테스트 코드
- 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용
2) 필드 주입 코드 작성
package hello.core.order;
@Component
public class OrderServiceImpl implements OrderService{
// 3. 필드 주입
@Autowired private final MemberRepository memberRepository;
@Autowired private final DiscountPolicy discountPolicy;
...
}
(참고) 순수 자바 테스트 코드에서는 @Autowired가 동작하지 않는다. @SpringBootTest 처럼 스프링 컨테이너를 테스트에 통합한 경우에만 가능하다.
4. 일반 메서드 주입
일반 메서드를 통해서 주입받는 방식이다.
1) 특징
- 한 번에 여러 필드를 주입 받을 수 있다.
- 일반적으로 잘 사용하지 않는다. (생성자, 수정자 주입에서 다 해결되기 때문에)
2) 일반 메서드 주입 코드 작성
package hello.core.order;
@Component
public class OrderServiceImpl implements OrderService{
// 일반 메서드에서 주입하기 때문에 final을 빼야 함
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
// 4. 일반 메서드 주입
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
...
}
의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다. 스프링 빈이 아닌 Member 같은 클래스에서 @Autowired 코드를 적용해도 아무 기능도 동작하지 않는다.
'Spring > 스프링 핵심 원리 - 기본편' 카테고리의 다른 글
[스프링 핵심 원리] 07. 의존관계 자동 주입 - 롬복과 최신 트랜드 (0) | 2022.05.18 |
---|---|
[스프링 핵심 원리] 07. 의존관계 자동 주입 - 옵션 처리 & 생성자 주입을 선택해라! (0) | 2022.05.18 |
[스프링 핵심 원리] 06. 컴포넌트 스캔 - 중복 등록과 충돌 (0) | 2022.05.18 |
[스프링 핵심 원리] 06. 컴포넌트 스캔 - 탐색 위치와 기본 스캔 대상 & 필터 (0) | 2022.05.18 |
[스프링 핵심 원리] 06. 컴포넌트 스캔 - 컴포넌트 스캔과 의존관계 자동 주입 시작하기 (0) | 2022.05.18 |