개인 프로젝트를 만들다가 @Autowired를 사용하여 의존성을 주입한 부분의 노란 전구를 발견했습니다.🤔
그냥 지나칠 수 없기에 한번 확인해보니 생성자를 사용하는 것을 저에게 권유하고 있습니다.
의존성 주입이란?
의존성 주입은 객체가 생성될 때 필요한 객체를 주입하는 것을 말합니다. 의존성 주입을 할 때는 필드 주입, 생성자 주입, setter 주입을 사용할 수 있습니다.
- 필드 주입 : 객체의 필드에 의존성을 주입하는 방법입니다.
- 생성자 주입 : 객체의 생성자에 의존성을 주입하는 방법입니다.
- setter 주입 : 객체의 setter 메서드에 의존성을 주입하는 방법입니다.
예시
필드 주입
public class UserService {
@Autowired
private UserRepository userRepository;
public void save(User user) {
userRepository.save(user);
}
}
생성자 주입
public class UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void save(User user) {
userRepository.save(user);
}
setter 주입
public class UserService {
private UserRepository userRepository;
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void save(User user) {
userRepository.save(user);
}
}
생성자 주입 권장 이유
1. 생성자 주입 순환 참조를 방지합니다.
순환 참조는 객체 A가 객체 B를 참조하고, 객체 B가 객체 A를 참조하는 것을 말합니다. 순환 참조가 발생하면 객체를 생성할 수 없거나, 객체의 메서드를 호출할 수 없습니다.
생성자 주입으로 testservice와 madservice가 서로를 참조한다면 컴파일 단계에서 에러가 발생하여 사용자에 알려줍니다.
*순환 참조는 설계 단계의 문제이므로 다시 설계해야 합니다.*
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| testService defined in file [~~~/TestService.class]
↑ ↓
| madService defined in file [~~~/MadService.class]
└─────┘
2 .생성자 주입은 의존성이 주입되지 않은 상태에서 객체가 생성될 수 없기 때문에 필드 주입보다 안전합니다.
3. 생성자 주입은 코드가 깨끗하고 테스트하기 쉽습니다.
/*UserService 클래스는 UserRepository 클래스의 인스턴스를 생성자 주입으로 주입받습니다.
UserService 클래스의 save() 메서드는 User 객체를 UserRepository 클래스에 저장합니다.*/
UserService userService = new UserService(new UserRepository());
userService.save(user);
4. 생성자 주입은 의존성의 결합도를 낮추는 데 도움이 됩니다.
5. 생성자 주입은 final을 사용할 수 있습니다
불변 객체나 null이 아님을 보장할 때 사용할 수 있으며, 다음은 TestRepository에 null을 참조하도록 변경하면 NullPointerException이 발생함을 보여주는 코드입니다.
@Service
public class TestService {
private final TestRepository TestRepository;
public TestService(TestRepository Testepository) {
this.TestRepository = TestRepository;
}
public void someMethod() {
//final을 사용함으로 NullPointerException이 발생
TestRepository = null;
}
}
final로 선언된 필드는 값을 변경할 수 없기 때문에 의존성 주입의 안전성을 높일 수 있습니다.
필드 주입은 간단하고 사용하기 쉽지만, 의존성이 주입되지 않은 상태에서 객체가 생성될 수 있기 때문에 취약할 수 있습니다. setter 주입은 필드 주입과 생성자 주입보다 유연하게 의존성을 주입할 수 있지만, 코드가 지저분해질 수 있습니다.
정리
1. 순환 참조를 방지
2. 코드가 깨끗하고 테스트하기 쉽다.
3. 불변성을 보장합니다.(final)
'일지' 카테고리의 다른 글
[MySQL] 계정 생성 시 에러 발생 (0) | 2023.07.13 |
---|---|
[보안] 리눅스 서버 패스워드 복잡성 설정하기 (0) | 2023.06.30 |
[Windows] hosts 파일 수정하기 (0) | 2023.06.15 |
[Linux] scp - ssh를 이용한 파일/디렉토리 복사 (0) | 2023.06.14 |
[Apache] Apache 웹서버 관련 파일 및 디렉토리 (0) | 2023.06.14 |
댓글