일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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
- EC2
- 네이티브쿼리
- AuthenticationEntryPoint
- 컨테이너실행
- 적용우선순위
- MySQL
- 예약
- querydsl
- 테스트메소드
- appspec
- 메세지수정
- 포트
- WeNews
- ㅔㄴ션
- appspec.yml
- docker명령어
- ubuntu
- 외부키
- foreignkey
- 참조키
- subquery
- 커밋메세지수정
- 서브쿼리
- Query
- 메소드명
- 테스트
- 추후정리
- 2 > /dev/null
- 검색
- application.yml
Archives
- Today
- Total
제뉴어리의 모든것
[Section2] [Spring Core] Spring Framework의 핵심 개념 - Spring DI 본문
다양한 의존관계 주입 방법
- 생성자 주입
- 수정자 주입 (setter 주입)
- 필드 주입
- 일반 메서드 주입
생성자 주입
생성자를 통해서 의존 관계를 주입 받는 방법입니다.
생성자에 @Autowired를 하면 스프링 컨테이너에 @Component로 등록된 빈에서 생성자에 필요한 빈들을 주입합니다.
- 특징
- 생성자 호출 시점에 딱 1번만 호출되는 것이 보장됩니다.
- 불변과 필수 의존 관계에 사용됩니다.
- 생성자가 1개만 존재하는 경우에는 @Autowired를 생략해도 자동 주입 됩니다.
- NullPointerException 을 방지할 수 있습니다.
- 주입받을 필드를 final 로 선언 가능합니다.
@Component
public class OrderServiceImpl implements OrderService {
private final UserRepository userRepository;
private final DiscountInfo discountInfo;
@Autowired
public OrderServiceImpl(UserRepository userRepository, DiscountInfo discountInfo) {
this.userRepository = userRepository;
this.discountInfo = discountInfo;
}
}
수정자 주입 (setter 주입)
setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존 관계를 주입하는 방법입니다.
- 특징
- 선택과 변경 가능성이 있는 의존 관계에 사용된다.
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.
-
@Component
public class OrderServiceImpl implements OrderService {
private UserRepository userRepository;
private DiscountInfo discountInfo;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Autowired
public void setDiscountInfo(DiscountInfo discountInfo) {
this.discountInfo = discountInfo;
}
}
필드 주입
필드에 @Autowired 붙여서 바로 주입하는 방법입니다.
- 특징
- 코드가 간결해서 예전에 많이 사용된 방식이지만, 외부에서 변경이 불가능하여 테스트하기 힘들다는 단점이 있습니다.
- DI 프레임워크가 없으면 아무것도 할 수 없습니다.
- 실제 코드와 상관 없는 특정 테스트를 하고 싶을 때 사용할 수 있습니다.
- 하지만 정상적으로 작동되게 하려면 결국 setter가 필요하게 되서 수정자 주입을 사용하는게 더 편리해집니다.
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private UserRepository userRepository;
@Autowired
private DiscountInfo discountInfo;
}
일반 메서드 주입
일반 메서드를 사용해 주입하는 방법입니다.
- 특징
- 한번에 여러 필드를 주입 받을 수 있습니다.
- 일반적으로 사용되지 않는다.
옵션 처리
주입할 빈이 스프링 컨테이너에 등록되지 않았음에도 프로그램이 작동되어야 하는 경우시 사용
- 자동 주입 대상 옵션 처리 방법
- @Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출되지 않게 됩니다.
- org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력됩니다.
- Optional<> : 자동 주입할 대상이 없으면 Optional.empty가 입력됩니다
- 옵션 처리 방법 코드
public class AutowiredAPP {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(Testbean.class);
}
static class Testbean{
@Autowired(required = false) // @Autowired(required=false)
public void setNoBean1(User noBean1) {
System.out.println("noBean1 = " + noBean1);
}
@Autowired
public void setNoBean2(@Nullable User noBean2) { //@Nullable
System.out.println("noBean2 = " + noBean2);
}
@Autowired
public void setNoBean3(Optional<User> noBean3) { //Optional<>
System.out.println("noBean3 = " + noBean3);
}
}
}
@Autowired(required=false) 로 설정된 메소드는 주입될 빈이 존재하지 않으면, 메소드가 호출조차 되지 않는다.
생성자 주입을 사용해야하는 이유
과거에는 수정자, 필드 주입을 많이 사용했지만, 최근에는 대부분 생성자 주입 사용을 권장합니다.
생성자 주입 사용 이유
- 불변
- 의존 관계 주입은 처음 애플리케이션이 실행될 때 대부분 정해지고 종료 전까지 변경되지 않고 변경되서는 안됩니다.
- 수정자 주입 같은 경우에는 이름 메서드를 public으로 열어두어 변경이 가능하기 때문에 적합하지 않습니다.
- (누군가 실수로 변경할 수도 있고, 애초에 변경하면 안되는 메서드가 변경할 수 있게 설계하는 것은 좋은 방법이 아닙니다.
- 생성자 주입은 객체를 생성할 때 최초로 1번만 호출되고 그 이후에는 다시는 호출되는 일이 없기 때문에 불변하게 설계할 수 있습니다.
- 누락
- 호출했을 때는 NPE(Null Point Exception)이 발생하는데 의존관계 주입이 누락되었기 때문에 발생합니다.
- 생성자 주입을 사용하면 주입 데이터 누락 시 컴파일 오류가 발생합니다.
- final 키워드 사용 가능
- 생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있습니다.
- 생성자에서 값이 설정되지 않으면 컴파일 시점에서 오류를 확인할 수 있습니다.
- java: variable (데이터 이름) might not have been initialized
- 생성자 주입을 제외한 나머지 주입 방식은 생성자 이후에 호출되는 형태이므로 final 키워드를 사용할 수 없습니다.
- 순환 참조
- 순환 참조를 방지할 수 있습니다.
- 개발하다보면 여러 컴포넌트 간에 의존성이 생기게 됩니다. (A → B를 참조하고, B → A를 참조)
- 필드 주입과 수정자 주입은 빈이 생성된 후에 참조를 하기 때문에 애플리케이션이 어떠한 오류와 경고 없이 구동됩니다.
- 실제 코드가 호출될 때까지 문제를 알 수 없습니다.
- 생성자를 통해 주입하게되면 BeanCurrentlyInCreationException이 발생하게 됩니다.
결론
대부분에 경우에 생성자 주입을 사용하고, 꼭 필요한 부분에서만 수정자 주입을 고려해보자.
생성자 주입 방식의 장점 요약
- 의존관계 설정이 되지 않으면 객체생성이 불가능합니다.
- 컴파일 타임에 인지가 가능합니다.
- NPE 에러 방지가 가능합니다.
- 의존성 주입이 필요한 필드를 final 로 선언 가능합니다.
- (스프링에서) 순환참조 감지가 가능합니다.
- 순환 참조 시 앱구동이 실패하게 됩니다.
- 테스트 코드 작성 용이합니다.
- 수정자 주입이 필요한 경우가 있을 수 있지만 옵션이 필요할 때만 선택하면 됩니다.
'코드스테이츠 > 정리 블로깅' 카테고리의 다른 글
[Section2] [Spring Core] Spring Framework의 핵심 개념 - 스프링 컨테이너와 빈 (0) | 2022.08.13 |
---|---|
[Section2] [Spring Core] Spring Framework의 핵심 개념 - Component Scan (0) | 2022.08.12 |
[Section2] [Spring Core] Spring Framework의 핵심 개념 - 자바 기반 컨테이너 설정 (0) | 2022.08.12 |
[Section2] [관계형 데이터베이스] [Spring Core] Spring Framework 기본 2 (0) | 2022.08.10 |
[Section2] [관계형 데이터베이스] [Spring Core] Spring Framework 기본 (0) | 2022.08.09 |