일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- post
- Spring
- 라우터
- 방화벽
- map
- Jenkins
- tomcat
- 캐시서버
- Java
- gradle
- 소켓
- jdk
- Collection
- ansible
- sonarQube
- Pipeline
- cloud
- 허브
- JPA
- LAN어댑터
- mybatis
- AOP
- DevOps
- Set
- IntelliJ
- docker
- container
- 액세스회선
- STREAM
- Linux
- Today
- Total
거북이-https://velog.io/@violet_evgadn 이전완료
DI 주입 실습 본문
생성자 주입
@Component
public class UserService {
private final MemberService memberService;
private final VIPService vipService;
@Autowired
public UserService(MemberService memberService, VIPService vipService){
this.memberService = memberService;
this.vipService = vipService;
}
public void greet(){
System.out.println("********");
memberService.greeting();
vipService.greeting();
System.out.println("********");
}
}
먼저 MemberSerivce와 VIPService는 이미 Spring Bean으로 등록되어 있다고 가정하자.
Test를 위해선 UserService도 bean에 등록되어 있어야 하기 때문에 @Component 어노테이션을 활용했다.
생성자 주입은 말 그대로 "생성자" 기법으로 필요한 의존성들을 주입하는 방식을 의미한다.
위 코드에서는 `public UserService()` 생성자를 통해 생성자 주입을 구현한 것이다.
앞서 말했듯이 Spring은 "생성자 주입" 기법을 강력하게 추천하고 있다. 그래서인지 생성자 주입에 한해서는 @Autowired 어노테이션을 활용하지 않아도 클래스에 @Component 어노테이션이 붙어있고 생성자가 하나만 존재한다면 자동으로 생성자 주입이라고 판단한다.
위 예시 코드에서는 생성자가 1개이고 @Component 어노테이션이 활용되고 있으므로 @Autowired 어노테이션이 없다고 하더라도 자동으로 생성자 주입으로 DI가 구현된다.
여기서 주의 깊게 봐야하는 것은 "private final ~"이다. 오직 생성자 주입만이 final으로 의존성 객체를 활용할 수 있어 불변성을 가진다. 전에 말했듯 의존성 객체가 변경되는 경우는 거의 존재하지 않으므로 final으로 의존성 객체의 접근제어자를 설정해 놓는 것에 습관을 들여놓자.
생성자 주입의 장점 중 하나는 Lombok과의 결합을 통한 편리한 코딩이었다. 이를 활용해보자.
@RequiredArgsConstructor
@Component
public class UserService {
private final MemberService memberService;
private final VIPService vipService;
public void greet(){
System.out.println("********");
memberService.greeting();
vipService.greeting();
System.out.println("********");
}
}
먼저 Convention으로 Lombok 어노테이션은 클래스와 가장 멀리 떨어진 위치에 입력하기로 했기 때문에 가장 위에 붙였다.
@RequiredArgsConstructor는 @NonNull이나 final이 붙은 Field에 대해 자동으로 생성자를 생성해주는 Lombok 어노테이션이다.
(나중에 Lombok 어노테이션을 한번에 정리할 때가 있을 것이다)
즉, 위 Case에서는 final이 붙은 MemberService와 VipService를 입력받는 생성자를 자동으로 만들어 준다는 것이다
위에서 설명했듯 Spring은 생성자가 한 개만 존재하면 생성자 주입을 활용한다고 인지하기 때문에 @RequiredArgsConstructor는 @Autowired 어노테이션을 생성자에 붙여주지 않지만 Spring 측에서 생성자 주입으로 구현되었다고 판단하는 것이다.
여기서 중요한 점!
@RequiredArgsConstructor는 결국 "final이 붙은" Field에 대해 생성자를 만들어주므로 Lombok을 활용하기 위해선 "필수적으로" final을 활용해야 한다는 것이다
필드 주입
필드 주입은 실제 프로젝트에는 많이 활용하지 않고 단위 테스트 등에서 많이 활용한다고 했다.
그럼 실제로 위에서 썼던 생성자 주입 코드가 제대로 작동하는지 알아보는 코드를 통해 필드 주입 기법을 알아보자.
@SpringBootTest
class ReviewApplicationTests {
@Autowired
UserService userService;
@Test
void contextLoads() {
userService.greet();
}
}
필드 주입은 객체에 @Autowired 어노테이션만 활용하면 되기 때문에 쉬운 주입이 큰 장점이다.
위 코드를 보더라도 UserService 객체를 Bean에서 끌어오기 위해 단순히 userService 객체에 @Autowired만 붙여 바로 필드 주입 구현이 완료되었음을 볼 수 있다.
필드 주입은 여러 단점을 가지기 때문에 실제 프로젝트에서는 활용하지 않지만 위 코드에서 볼 수 있듯 단위 테스트를 할 때는 매우 편리한 도구가 되기 때문에 단위 테스트 시에는 활용을 고려해보자
참고로, 결과는 아래 사진과 같다. 생성자 주입이 잘 구현되었음을 알 수 있다
수정자 주입(Setter 주입)
@Component
public class UserService {
private MemberService memberService;
private VIPService vipService;
@Autowired
public void setVipService(VIPService vipService) {
this.vipService = vipService;
}
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
Setter 주입은 정말로 프로젝트를 하면서 단 한 번도 활용해본 적이 없는 주입 방법이다.
의존성 객체가 Null인데도 애플리케이션이 구동되어 UserServiec 객체가 생성될 수 있다는 위험성에도 불구하고 편리성도 없는 그저 애매한 주입 방법일 뿐이다.
그러니, 그냥 "이런 방식도 있구나~" 정도로만 알고 가자
(참고로, Setter 주입은 Setter마다 @Autowired 어노테이션을 일일이 붙여줘야 한다. 파면 팔수록 활용 이유가 모호해지는 DI 방법이다)
'웹 개발 > Spring(활용)' 카테고리의 다른 글
build.gradle 사용법 (0) | 2022.11.27 |
---|---|
Spring Web 메인 클래스 (0) | 2022.08.05 |
AOP 실습 (0) | 2022.08.04 |
스프링 빈 활용 (0) | 2022.08.03 |