테스트 환경

JDK 1.6
CGLib 2.1_3 nodep
Spring 2.5.5

테스트 클래스

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations="springContext.xml")
public class HelloAspectTest{

    @Autowired
    Hello goodHelloImpl;
   
    @Test
    public void createProxy() throws Exception {
        assertNotNull(goodHelloImpl);
        StopWatch stopWatch = new StopWatch();
        testProxiedMethod(10, stopWatch);
        System.out.println("total " + stopWatch.getTotalTimeMillis());
    }

    private void testProxiedMethod(int count, StopWatch stopWatch) {
        while(count > 0){
            stopWatch.start();
            for(int i = 0 ; i < 1000000 ; i++)
                goodHelloImpl.hi();
            stopWatch.stop();
            System.out.println(stopWatch.getLastTaskTimeMillis());
            count--;
        }
       
    }
}

CGLib을 사용할 때는 Concrete class 타입을 써도 상관없는데, JDK 프록시를 사용할 때는 인터페이스 타입을 써야 합니다. 이유는 아시죠? 설명은 패스합니다.

StopWatch 클래스는 스프링이 제공해주는건데, 위처럼 요긴하게 쓸 수 있습니다. API는 설명이 필요 없을 만큼 작명을 잘 해뒀기 때문에 그냥 읽어보시면 어떤 일을 하는지 알 수 있으실 겁니다.

스프링 설정 파일

    <context:component-scan base-package="org.opensprout.sandbox.proxy">
        <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect" />
    </context:component-scan>

    <aop:aspectj-autoproxy proxy-target-class="true" />

윗 부분에 주의해야 합니다. proxy-target-class="true" 이 설정을 삭제하면, JDK 프록시를 사용하는 것이고, 저 설정 그대로면, CGLib을 사용하는 겁니다.

어드바이스 적용 대상 인터페이스 => 타겟 인터페이스

public interface Hello {
   
    public String hi();

}

어드바이스 적용 대상 구현체 => 타겟 클래스

@Component
public class GoodHelloImpl implements Hello {
   
    public String hi(){
        return "";
    }

}

클래스 이름이나 메소드 이름 등에 너무 신경쓰지 말아주세요. 흑흑..ㅠ.ㅠ 대충 만든거란 말에요. 그것 보단, 이 녀석이 인터페이스를 구현하고 있기 때문에, 스프링이 프록시를 만들 때 proxy-target-class="true" 이 설정이 없으면 기본적으로 JDK 프록시를 생성한다는 사실.. 아시죠?

자 그럼 이제부터 쇼타임.

1. CGLib 사용시

위 설정 그대로 입니다.

1250
1204
1203
1218
1204
1203
1203
1219
1218
1219
total 12141

2. JDK 프록시 사용시

스프링 설정에서  proxy-target-class="true" 이걸 삭제합니다.

1687
1657
1656
1656
1656
1672
1672
1672
1656
1656
total 16640

3. CGLib 프록시를 서버 모드로

위 설정 그대로 사용합니다.
테스트 실행시 VM 인자에 -server 추가합니다.

813
796
797
813
797
797
812
797
797
total 8172

4. JDK 프록시를 서버 모드로

스프링 설정에서  proxy-target-class="true" 이걸 삭제합니다.
테스트 실행시 VM 인자에 -server 추가합니다.

1078
922
922
937
906
938
906
922
937
938
total 9406

캬요~ 자바지기님께서 테스트 했을 때에 비하면 JDK 프록시 성능 많이 좋아졌죠?