순환참조오류 - The dependencies of some of the beans in the application context form a cycle

wish17·2023년 4월 8일
0

오류정리

목록 보기
3/7
2023-04-08 06:34:09.984 ERROR 20068 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

┌─────┐
|  customAuthorityUtils (field private org.springframework.security.core.userdetails.UserDetailsService com.codestates.auth.CustomAuthorityUtils.userDetailsService)
↑     ↓
|  memberDetailsService defined in file [D:\AAWonJong\it\spring\Section4\be-template-spring-security-jwt-basic\build\classes\java\main\com\codestates\auth\MemberDetailsService.class]
└─────┘


Action:

Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.

오류발생 풀코드 Github

각 클래스들간의 관계를 주의깊게 생각하지 않고 기능구현을 하다보니 해당 오류가 발생했다.

문제가 되는 부분은 CustomAuthorityUtils 클래스와 MemberDetailsService 클래스 사이의 순환 참조다.

CustomAuthorityUtils 클래스에 있는 userDetailsService 필드는 MemberDetailsService 클래스를 참조하고 있고, MemberDetailsService 클래스는 CustomAuthorityUtils 클래스를 참조하고 있기 때문이다.

//변경 전
public boolean isAdmin(String username) {
    UserDetails userDetails = memberDetailsService.loadUserByUsername(username);
    Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();

    return authorities.stream()
            .anyMatch(authority -> authority.getAuthority().equals("ADMIN"));
}


//변경 후
public boolean isAdmin(UserDetails userDetails) {
    Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();

    return authorities.stream()
            .anyMatch(authority -> authority.getAuthority().equals("ROLE_ADMIN"));

}

MemberDetailsService에 대한 의존성을 제거하고, 대신 UserDetails 객체를 인자로 받아서 isAdmin 메소드를 호출할 수 있도록 수정해서 해결했다.

isAdmin()메서드를 호출하는 OrderService 클래스의 isOrderOwnerOrAdmin()메서드는 아래와 같이 수정했다.

//수정 전
public boolean isOrderOwnerOrAdmin(long orderId, String username) { // 주문주인 or 관리자인지 확인
    try {
        Optional<Order> optionalOrder = orderRepository.findById(orderId);
        if (optionalOrder.isPresent()) {
            Order order = optionalOrder.get();
            if (order.getMember() != null) {
                return order.getMember().getName().equals(username) || authorityUtils.isAdmin(username);
            } else { // 주문한 사용자가 아닐 때
                log.error("본인 주문에만 접근 가능합니다.", orderId);
            }
        } else { // 주문이 없을 때 처리
            log.error("존재하지 않는 주문입니다.", orderId);
        }
    } catch (Exception e) { // 데이터베이스 연결 문제 등의 예외 처리
        log.error("주문 ID: {} 조회 중 오류가 발생했습니다. 오류: {}", orderId, e.getMessage());
    }
    return false;
}


//수정 후
public boolean isOrderOwnerOrAdmin(long orderId, String username) { // 주문주인 or 관리자인지 확인
    try {
        Optional<Order> optionalOrder = orderRepository.findById(orderId);
        if (optionalOrder.isPresent()) {
            Order order = optionalOrder.get();
            if (order.getMember() != null) {
                UserDetails userDetails = memberDetailsService.loadUserByUsername(username);
                Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();

                boolean isAdmin = authorities.stream()
                        .anyMatch(authority -> authority.getAuthority().equals("ROLE_ADMIN"));

                return order.getMember().getName().equals(username) || isAdmin;
            } else { // 주문한 사용자가 아닐 때
                log.error("본인 주문에만 접근 가능합니다.", orderId);
            }
        } else { // 주문이 없을 때 처리
            log.error("존재하지 않는 주문입니다.", orderId);
        }
    } catch (Exception e) { // 데이터베이스 연결 문제 등의 예외 처리
        log.error("주문 ID: {} 조회 중 오류가 발생했습니다. 오류: {}", orderId, e.getMessage());
    }
    return false;
}

authorityUtils.isAdmin(username) 대신 UserDetails를 사용하여 사용자의 권한을 확인했다.

0개의 댓글