Skip to main content Link Menu Expand (external link) Document Search Copy Copied

created at 2024-05-17

Table of contents

  1. Spring Proxy

Spring Proxy

  • Proxy = 대리자
  • Spring 에서 프록시는 매우 많은 곳에서 사용
    • AOP 로 로직 감싸서 처리한는 부분.
    • Lazy Initialization
    • Security
    • Transaction Management
    • 등등

예를 들어서 이런식임.

class UserService(
    private val userRepository: UserRepository
) {
    fun save(user: User) {
        userRepository.save(user)
    }
}

UserRepository 가 interface 라면, UserService 는 Proxy 객체가 매핑. 그리고 이 프록시 객체는 UserRepository 인터페이스를 구현한 클래스와 연결됨. 즉, interface -> proxy -> impl class 객체 이런식으로 매핑시켜주는 녀석이 Proxy 임.

그리고 이런 인터페이스를 기반으로한 프록시 구현방식을 JDK Dynamic Proxy 라고 함. 클래스 기반의 방식인 CGLIB 도 있음.

  1. JDK Dynamic Proxy
    • 설정: proxyTargetClass = false 또는 인터페이스를 상속받은 경우 자동으로 사용
    • 작동 방식: 인터페이스를 상속받아 프록시 객체를 생성합니다. 인터페이스를 구현한 클래스를 대상으로 합니다.
  2. CGLIB Proxy
    • 설정: proxyTargetClass = true
    • 작동 방식: 인터페이스가 아닌 클래스를 상속받아 프록시 객체를 생성합니다. 이를 통해 인터페이스가 없는 클래스도 프록시를 통해 DI 및 AOP 기능을 사용할 수 있습니다.
  • interface -> abstract class -> impl class

nGrinder 는 이런식으로 구조를 잡고 설계되어 있음. 좀 더 유연하고 안전하게 사용할 수 있기 때문이죠.

좀 더 유연하고 안전하게 사용할 수 있기 때문이죠. 그래서 저도 이런식으로 구조잡고 진행했더니! 실제 객체가 매핑되지 않고 프록시 객체가 매핑되는 경우가 있었습니다.

여기서 Spring 이 프록시 객체를 매핑하는 방법은 두 가지가 있습니다.

interface -> abstract class -> @Service extended class 이런 경우에는 CGLIB Proxy 가 사용되어야하죠

하지만, spring 에서는 interface 를 상속받는 클래스의 구현체와 프록시가 매핑됩니다.

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void save(User user) {
        System.out.println("save user");
    }
}