스프링에서 final을 쓰면 안되는 이유 (feat. CGLIB)
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자 대상자_정보 출력
- Spring 프레임워크 사용자 (특히 AOP, 프록시 기반 개발자)
- 중급 이상 Java 개발자 (프록시 메커니즘 이해 필요)
- 실무에서 @Repository/@Component 사용자
핵심 요약
@Repository
로 선언한 클래스에final
을 붙이면 CGLIB 프록시 생성 실패 -> Null Pointer Exception 발생final
메서드는 프록시로 래핑되지 않아 필드 참조 시 null 발생 -> 예상치 못한 NPE 발생@Component
대신@Repository
사용 시 프록시 생성 차이로 동작 불일치 -> AOP 적용 범위 차이
섹션별 세부 요약
###1. 문제 상황
@Repository
사용 시 NPE 발생,@Component
사용 시 정상ReservationRepository
의dao
필드가 null로 초기화- 생성자에서는 정상 주입, 메서드 호출 시 null 발생
###2. 프록시 메커니즘
- Spring AOP는 JDK Dynamic Proxy/CGLIB Proxy 사용
- CGLIB는
final
클래스/메서드를 상속 불가능 -> 프록시 생성 실패 - CGLIB 프록시는 원본 객체를 MethodInterceptor로 접근 -> 필드 초기화 시 null
###3. final
메서드의 문제
final
메서드는 프록시에 래핑되지 않음- 프록시 객체의
final
메서드 호출 시 실제 필드가 초기화되지 않음 -> NPE 발생 - 예:
finalMethod()
호출 시this.dao
가 null
###4. 해결 및 예방
final
키워드를 클래스/메서드에 사용하지 않도록 권장@Component
대신@Repository
사용 시 AOP 적용 범위 차이 주의@Transactional
메서드에final
사용 시 트랜잭션 적용 실패
결론
- Spring 빈에
final
키워드 사용은 프록시 생성을 방해 -> NPE 발생 가능성 - CGLIB 프록시 메커니즘 이해 필수 (Spring 6.2.5 기준)
- AOP 적용 대상 메서드에
final
사용은 피하고,@Component
보다@Repository
사용 시 주의