Free Lines Arrow
본문 바로가기
Spring/Spring 고급

[Spring] CGLIB

by skahn1215 2023. 4. 18.
728x90
반응형

CGLIB(code generator library)

  • 바이트 코드를 조작해서 동적으로 클래스를 생성하는 기술을 제공하는 라이브러리
  • jdk와 달리 인터페이스가 필요없다.

 

 

CGLIB 예제

CGLIB 은 MethodInterceptor를 제공한다.

package org.springframework.cglib.proxy;
  public interface MethodInterceptor extends Callback {
      Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) 
      throws Throwable;
  }
  • obj :  CGLIB이 적용된 객체
  • method: 호출된 메소드
  • args: 메서드를 호출하면서 전달된 인수
  • proxy: 메서드 호출에 사용

 

 

UserServiceImpl

  • interface를 상속받지 않은 클래스
package com.example.exercise.aop.cglib;

import com.example.exercise.aop.jdk.UserServiceInterface;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class UserServiceImpl {
    public void save() {
        log.info("save user info");
    }
}

 

LogInvocationHandler

  • MethodInterceptor를 구현한 클래스 여기서 공통 로직을 수행한다.
package com.example.exercise.aop.cglib;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;


@Slf4j
public class LogInvocationHandler implements MethodInterceptor {

    private final Object target;

    public LogInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        log.info("실행 전 로그");
        Object result = proxy.invoke(target, args);
        log.info("실행 후 로그");

        return result;
    }
}

 

 

 

TestCode

package com.example.exercise.aop.cglib;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.cglib.proxy.Enhancer;

@Slf4j
class LogInvocationHandlerTest {

    @Test
    void cglib() {
        UserServiceImpl target = new UserServiceImpl();

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(new LogInvocationHandler(target));

        UserServiceImpl proxy = (UserServiceImpl) enhancer.create();

        log.info("target class={}", target.getClass());
        log.info("proxy class={}", proxy.getClass());

        proxy.save();
    }

}

 

 

실행결과

  • proxy class 를 보면 CGLIB로 생성되어 있는걸 확인 할 수 있다.
21:21:16.852 [Test worker] INFO com.example.exercise.aop.cglib.LogInvocationHandlerTest -- target class=class com.example.exercise.aop.cglib.UserServiceImpl
21:21:16.854 [Test worker] INFO com.example.exercise.aop.cglib.LogInvocationHandlerTest -- proxy class=class com.example.exercise.aop.cglib.UserServiceImpl$$EnhancerByCGLIB$$6d9d94f3
21:21:16.854 [Test worker] INFO com.example.exercise.aop.cglib.LogInvocationHandler -- 실행 전 로그
21:21:16.863 [Test worker] INFO com.example.exercise.aop.cglib.UserServiceImpl -- save user info
21:21:16.863 [Test worker] INFO com.example.exercise.aop.cglib.LogInvocationHandler -- 실행 후 로그

 

728x90
반응형

'Spring > Spring 고급' 카테고리의 다른 글

[Spring] Spring AOP 개념  (0) 2023.06.27
[Spring] AOP 개념  (0) 2023.06.15
[Spring] JDK Proxy  (0) 2023.04.18
[Spring] Proxy  (0) 2023.01.23

댓글