쌓고 쌓다
빈 순환 참조 발생 (The dependencies of some of the beans in the application context form a cycle) 본문
빈 순환 참조 발생 (The dependencies of some of the beans in the application context form a cycle)
승민아 2023. 8. 18. 21:44일대다 단방향 매핑에서 다대일 양방향 매핑으로 변경하고 이것저것 리팩토링하는 과정에서...
The dependencies of some of the beans in the application context form a cycle 에러가 발생했다.
예를 들어 설명하자면.
A 클래스 빈을 만드는 과정에서 B 클래스 빈을 주입해야하는 상황이다.
그래서 B 클래스 빈을 만들고자해서 B 클래스 빈을 만드는데 또 이 빈은 만드는데 A 클래스 빈을 주입 받아야하는 상황인것이다.
그럼 뭘 먼저 만들어야하는지 알 수 없기에
무한 참조가 일어나는 것이다.
그냥 필요할때마다 의존성 주입으로 끌어다 써도 문제 없을줄 알았던 나...
의존성을 잘 설계하는게 중요했었다. 양방향 의존성이라니!!
그러면 다른 서비스를 통해 만들어놓은 로직도 쓰고싶은데 어떻게 사용하라는건가...
https://www.baeldung.com/circular-dependencies-in-spring
다양한 해결방법이 있지만 두가지만 사용해보기로 했다.
해결 방법 (1)
public class PosterService {
private SpringDataJpaPosterRepository posterRepository;
private UploadFileService uploadFileService;
private FileStore fileStore;
@Autowired
public PosterService(SpringDataJpaPosterRepository posterRepository, @Lazy UploadFileService uploadFileService, FileStore fileStore) {
this.posterRepository = posterRepository;
this.uploadFileService = uploadFileService;
this.fileStore = fileStore;
}
}
@Lazy 어노테이션을 사용하여 빈을 Lazy하게 초기화하도록한다.
빈을 완전히 등록하는것이 아닌 프록시를 만들어 주입한다. 이 프록시는 빈이 완전히 필요할때만 생성된다.
그래도 설계 자체를 고치는게 올바른 방법인것 같다.
해결 방법 (2)
PosterService에서 UploadFileService도 써야하고
UploadFileService에서도 PosterService를 쓰면 좋을텐데...
순환구조를 뜯어고치는 방법이 젤 좋다.
@Service
public class UploadFileService {
public List<UploadFile> findByPno(Long pno) {
Poster poster = posterService.findByOne(pno).get(); // 문제
return uploadFileRepository.findByPoster(poster);
}
}
posterService의 findByOne 메서드를 사용하기위해 posterService를 주입 받으려고 했었다.
사실상 게시글 PK로 게시글을 찾는건 posterRepository로도 가능하기에 아래와 같이 수정했다.
@Service
public class UploadFileService {
private UploadFileRepository uploadFileRepository;
private SpringDataJpaPosterRepository posterRepository; // 변경된 부분
private FileStore fileStore;
@Autowired
public UploadFileService(UploadFileRepository uploadFileRepository, SpringDataJpaPosterRepository posterRepository, FileStore fileStore) {
this.uploadFileRepository = uploadFileRepository;
this.posterRepository = posterRepository; // 변경된 부분
this.fileStore = fileStore;
}
public List<UploadFile> findByPno(Long pno) {
Poster poster = posterRepository.findById(pno).get(); // 변경된 부분
return uploadFileRepository.findByPoster(poster);
}
}
'프로그래밍 > spring' 카테고리의 다른 글
메시지, 국제화 사용하기 (0) | 2023.08.21 |
---|---|
컨트롤러 모든 메서드 Model에 값 넣기 - @ModelAttribute (0) | 2023.08.20 |
PRG(Post-Redirect-Get) 패턴 (0) | 2023.08.15 |
[스프링 부트] 다중(멀티) 게시판으로 변경 - 23 (0) | 2023.08.14 |
HTTP 메시지 컨버터? (0) | 2023.08.13 |