개발/Spring Boot

[SpringBoot] @RequiredArgsConstructor 필요없는 소스 리팩토링 필드 주입 & 생성자 주입 차이 TIL

멋진놈 2023. 3. 3. 16:59
728x90

팀원 분이 저의 소스에 문제점을 지적해주었다. 그래서 그것을 앞으로 더이상 이상하게 사용하지 않고, 잘 쓰게끔 머릿 속에 저장 할 겸 이렇게 작성하게 되었다.

 

# 문제점 : 

 

@RequiredArgsConstructor

@RequiredArgsConstructor(생성자 주입)의 어노테이션과 나는 소스 안에서

 

@Autowired
ResourceLoader resourceLoader;

@Autowired(필드주입)의 어노테이션을 같이 사용하고 있었다. 

 

이것은 한마디로 같은 역할을 하는데, 두번 중복으로 쓰고 있다는 이야기다. 그래서 

@RequiredArgsConstructor을 사용하면, 

 

@Autowired 필드 주입은 사용할 필요 없고 그냥 final로만 적어주면 된다.

 

# 해결 : 

@RequiredArgsConstructor
private final ResourceLoader resourceLoader;

private final ResourceLoader resourceLoader; 만 해주면 생성자 주입이 된다. 

 

물론 @RequiredArgsConstructor을 안사용하면

@Autowired의 필드 주입으로 

ResourceLoader resourceLoader을 사용하면 됨. 그렇지만...

 

 

# 문제점2 : 

이렇게 주입 할 때 필드 주입은 선호 하지 않는다고 한다.

예를 들면, PdfService안에서 UserService내용을 가져와야하고, 그리고 UserService 안에서 PdfService의 내용을 가져와야할 때,  크로스 느낌.

=> 이것이 순환 참조 방지. 즉 객체 의존성을 추가하다 보면 순환 참조 문제가 발생할 수 있다.

순환 참조는 A -> B를 참조하면서, B -> A를 참조하는 경우 문제가 발생함. 
이렇게 서로 필드 주입을 하면은, 순환 참조로 인해 서버가 죽는다고함.

 

그래서 이런식으로 사용할 때는 @Autowired를 사용하지말고, 생성자 주입 @RequiredArgsConstructor을 사용하자.

 

 

※ 참고

@RequiredArgsConstructor 어노테이션을 안쓰면, 

 

private final ResourceLoader resourceLoader;

public PdfServiceImpl(ResourceLoader resourceLoader) {
    this.resourceLoader = resourceLoader;
}

를 사용하면 된다. 

 

 = 

 

 

아래와 같은 의미 

@RequiredArgsConstructor
public class boardImpl implements boardService {
    private final ResourceLoader resourceLoader;
}