Spring CGLlB 동적 에이전트 구현 프로 세 스 분석

JDK 동적 에이 전 트 는 사용 하기 매우 간단 하지만 한계 도 있다.이것 은 JDK 동적 에이 전 트 는 하나 이상 의 인 터 페 이 스 를 실현 해 야 하기 때문이다.인 터 페 이 스 를 실현 하지 않 으 려 면 CGLIB 에이 전 트 를 사용 할 수 있 기 때문이다.
CGLIB(Code Generation Library)는 고성능 오픈 소스 코드 생 성 패키지 로 많은 AOP 프레임 워 크 에 의 해 사용 되 고 있 으 며,바 텀 은 작고 빠 른 바이트 처리 프레임 워 크 ASM(Java 바이트 조작 프레임 워 크)을 사용 하여 바이트 코드 를 변환 하고 새로운 종 류 를 생 성 하 는 것 이다.따라서 CGLIB 는 ASM 가방 에 의존 하여 Spring 의 핵심 패키지 인 spring-core-3.2.2.RELEASE.jar 를 압축 해제 해 야 합 니 다.파일 디 렉 터 리 는 그림 1 참조.

그림 1 spring-core-3.2.2.RELEASE.jar 파일
그림 1 에서 알 수 있 듯 이 압축 해제 의 핵심 가방 에는 cglib 와 asm 이 포함 되 어 있다.즉,Spring 3.2.13 버 전의 핵심 가방 은 CGLIB 가 필요 로 하 는 가방 이 통합 되 어 있 기 때문에 ASM 의 JAR 가방 을 따로 가 져 올 필요 가 없다 는 것 이다.다음은 사례 를 통 해 CGLIB 를 실현 하 는 대리 과정 을 보 여 준다.
1.대상 클래스 GoodsDao 만 들 기
com.mengma.dao 패키지 에서 목표 클래스 GoodsDao 를 만 듭 니 다.클래스 에서 추가,삭제,변경,검사 방법 을 정의 하고 모든 방법 에서 출력 문 구 를 작성 합 니 다.다음 과 같 습 니 다.

package com.mengma.dao;

public class GoodsDao {
  public void add() {
    System.out.println("    ...");
  }

  public void update() {
    System.out.println("    ...");
  }

  public void delete() {
    System.out.println("    ...");
  }

  public void find() {
    System.out.println("    ...");
  }
}
2.프 록 시 클래스 MyBeanFactory 만 들 기
src 디 렉 터 리 아래 에 com.mengma.cglib 라 는 가방 을 만 듭 니 다.이 가방 아래 에 MyBean Factory 를 만 듭 니 다.다음 과 같 습 니 다.

package com.mengma.cglib;

import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.mengma.dao.GoodsDao;
import com.mengma.jdk.MyAspect;

public class MyBeanFactory {
  public static GoodsDao getBean() {
    //      
    final GoodsDao goodsDao = new GoodsDao();
    //        
    final MyAspect myAspect = new MyAspect();
    //      ,CGLIB    ,         ,  
    Enhancer enhancer = new Enhancer();
    //         
    enhancer.setSuperclass(goodsDao.getClass());
    //       
    enhancer.setCallback(new MethodInterceptor() {
      // intercept     jdk invoke,       jdk invoke― 
      @Override
      public Object intercept(Object proxy, Method method, Object[] args,
          MethodProxy methodProxy) throws Throwable {
        myAspect.myBefore(); //    
        Object obj = method.invoke(goodsDao, args); //       
        myAspect.myAfter(); //    
        return obj;
      }
    });
    //      
    GoodsDao goodsDaoProxy = (GoodsDao) enhancer.create();
    return goodsDaoProxy;
  }
}
위 코드 에는 CGLIB 의 핵심 클래스 인 Enhancer 가 적 용 됩 니 다.19 번 째 줄 코드 에서 Enhancer 류 의 set Superclass()방법 을 호출 하여 대상 을 확정 합 니 다.
21 번 째 줄 코드 는 setCallback()방법 으로 리 셋 함 수 를 추가 합 니 다.24 줄 코드 의 intercept()방법 은 JDK 동적 에이전트 방식 의 invoke()방법 에 해당 합 니 다.이 방법 은 목표 방법 이 실 행 된 전후 에 절단면 류 의 방법 을 강화 합 니 다.33~34 줄 코드 는 Enhancer 류 의 create()방법 으로 프 록 시 클래스 를 만 들 고 마지막 으로 프 록 시 클래스 를 되 돌려 줍 니 다.
3.테스트 클래스 만 들 기
com.mengma.cglib 패키지 에 테스트 클래스 CGLIBProxyTest 를 만 듭 니 다.편집 후 다음 과 같 습 니 다.

package com.mengma.cglib;

import org.junit.Test;
import com.mengma.dao.GoodsDao;

public class CGLIBProxyTest {
  @Test
  public void test() {
    //           (   spring  ,         )
    GoodsDao goodsDao = MyBeanFactory.getBean();
    //     
    goodsDao.add();
    goodsDao.update();
    goodsDao.delete();
    goodsDao.find();
  }
}
상기 코드 에서 getBean()방법 을 호출 할 때 goodDao 의 대리 대상 을 얻 은 다음 에 이 대상 을 호출 하 는 방법 입 니 다.JUnit 테스트 실행 test()방법 을 사용 하여 실행 에 성공 하면 콘 솔 의 출력 결 과 는 그림 2 와 같 습 니 다.

그림 2 출력 결과
그림 2 의 출력 결 과 를 보면 목표 클래스 를 호출 하 는 방법 전후 에 도 강 화 된 코드 를 성공 적 으로 호출 한 것 을 알 수 있다.이 는 CGLIB 에이 전 트 를 사용 하 는 방식 도 수 동 에이 전 트 를 실현 했다 는 것 을 의미한다.
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기