spring에서 의존성 주입하는 세가지 방법에 대해 정리하려 한다.
- DI(Dependency Injection)란?
- 필드 주입(Field Injection)
- 생성자 주입(Constructor Injection)
- 수정자 주입(Setter Injection)
- 차이점?
스프링 환경에서 개발한다하면 필수적으로 알아야할 특징인 Ioc, DI, AOP, POJO...등이 있는데, 너무나도 잘 정리되있는 글들이 많기 때문에 설명은 생략하겠다.
그중에서 DI(Dependency Injection) 의존성주입 이란 IoC 패턴의 구현방법중 하나이다.
즉, 필요한 객체는 자기가 직접 생성하는 것이 아니라 이미 생성된 객체(빈)을 주입받아 사용하는것!
IoC(Inversion of Control)?
객체의 생성과 관리를 개발자가 아닌 프레임워크, ioc컨테이너가 직접 관리하는것.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
@Autowired로 주입을 받는 방법.
사용하고자 하는 클래스에 주입받고자 하는 bean을 필드로 선언한 뒤 @Autowired 키워드를 붙여주면 자동으로 주입된다.
스프링 3.x 에서 권고하던 방식. set method를 정의해서 주입받는 방식이다.
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
@Service
public class UserService {
private UserRepository userRepository;
// 주입받을 객체가 하나면 @Autowired 생략 가능.
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
스프링에서 가장 권고하는 방식. (이유는 아래에 설명)
생성자를 통해서 주입받는 방식인데, 생성자를 만들어야하는 귀찮음(?)이 단점이다.
하지만 이부분도 @RequiredArgsConstructor 이용하여 아래처럼 간결한 코드를 작성할 수있다.
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
}
@RequiredArgsConstructor
final 이나 @NotNull이 붙은 필드의 생성자를 자동으로 생성해주는 어노테이션.
이 세가지 모두 빈을 주입받는 방법이지만, 차이가 있다.
필드 주입이나 수정자 주입은 런타임 시에 의존성을 주입하기때문에 의존성을 주입하지 않아도 객체가 생성된다.
하지만, 생성자 주입은 객체가 생성되는 시점에 빈을 주입하여, 런타임 전에 의존성이 주입되지 않아 발생할 수 있는 NPE를 방지 할 수 있다.
이 이유때문에 스프링에서는 현재 생성자 주입을 권고하고있고, 그 외에 다음과 같은 장점이 있다.
https://devlog-wjdrbs96.tistory.com/165
https://velog.io/@gillog/Spring-DIDependency-Injection-%EC%84%B8-%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95
https://baek.dev/post/21/