Java动态代理(JDKProxy与CGlibProxy)

来源:互联网 发布:ubuntu配置jdk1.8 编辑:程序博客网 时间:2024/06/12 00:44

代理模式是什么?

代理模式,也叫委托模式;看过电影 间谍之桥 一定对汤姆.汉克斯精悍的演技印象深刻,在这部电影中由他饰演詹姆士·唐纳文一个美国律师和苏联驻德官员在东德谈判;两国政府由于各种原因不能直接出面,分别派出代表来谈,但达成协议后执行实际还是由两国执行的;对象不直接交互,只负责实际操作,由代理对象交互,这就是代理模式。+ω+
上图地干活(UML):

什么是Java动态代理?

在传统的模式下,如果我们要给一个类写一个代理类,需要首先实现这个类实现的接口,然后在内部持有被代理对象,在执行方法时在代理对象中执行被代对象的方法;如果需要被代理的类很多,保证让你写到爽歪歪, ̄ω ̄,会出人命的。
Java动态代理就在这种情况下出现了,>ω<,它可以自动地给类生成代理类,这样就节省了大量时间,Spring框架中就大量使用JDKProxy和CGlibProxy技术来实现AOP(面向切面编程),来实现事务控制、日志打印等操作。

JDKProxy和CGlibProxy区别是什么?

JDKProxy是JDK提供的一种动态代理方式,不需要引入jar包,但其限制是代理类和被代理类必须实现相同接口,如果被代理类是继承的类那就抓瞎了。
CGlibProxy需要引入第三方jar包(cglib),它可以直接给代理类生成一个子类,没有必须实现自相同的接口限制。

        <dependency>            <groupId>cglib</groupId>            <artifactId>cglib</artifactId>            <version>3.2.1</version>        </dependency>

JDKProxy、CGlibProxy例子。

public interface HelloService {    void sayHello(String name);}//被代理类public class HelloServiceImpl implements HelloService {    public void sayHello(String name) {        System.out.println("Hello:"+name);    }}//JDK实现方式public class JdkProxy {    public static <T> T getJdkProxy(final T source) {        return (T) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces(), new InvocationHandler() {            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {                System.out.println("before");                Object result = method.invoke(source, args);                System.out.println("end");                return result;            }        });    }}//cglib实现方式public class CglibProxy {    public static <T> T getCglibProxy(final T source) {        MethodInterceptor methodInterceptor = new MethodInterceptor() {            public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {                System.out.println("before");                Object result = method.invoke(source, args);                System.out.println("end");                return result;            }        };        //创建代理对象        Enhancer enhancer = new Enhancer();        //设置代理类加载对象        enhancer.setClassLoader(source.getClass().getClassLoader());        //设置代理类继承父类        enhancer.setSuperclass(source.getClass());        //设置回调方法        enhancer.setCallback(methodInterceptor);        return (T) enhancer.create();    }}

测试代码

    @Test    public void test1() throws IOException {        HelloService helloServiceImpl = new HelloServiceImpl();        HelloService helloServiceJdkProxy = JdkProxy.getJdkProxy(helloServiceImpl);        HelloService helloServiceCglibProxy = CglibProxy.getCglibProxy(helloServiceImpl);        Long beginTime1 = System.nanoTime();        for (int i = 0; i < 1000000000; i++) {            helloServiceImpl.sayHello("wrh");        }        Long endTime1 = System.nanoTime();        Long beginTime2 = System.nanoTime();        for (int i = 0; i < 1000000000; i++) {            helloServiceJdkProxy.sayHello("wrh");        }        Long endTime2 = System.nanoTime();        Long beginTime3 = System.nanoTime();        for (int i = 0; i < 1000000000; i++) {            helloServiceCglibProxy.sayHello("wrh");        }        Long endTime3 = System.nanoTime();        System.out.println("Base:" + (endTime1 - beginTime1));      //3004676032        System.out.println("JdkProxy:" + (endTime2 - beginTime2));  //68836851401        System.out.println("CglibProxy:" + (endTime3 - beginTime3));//67284922866    }

直接调用、JDKProxy调用、CGlibProxy调用效率比较。

通过测试JDKProxy与CGlibProxy调用速度相差不大;但与直接调用差距巨大,是直接调用所耗费时间20倍。
为什么需要这么多时间呢?同时JDKProxy与CGlibProxy生成的class是什么呢?它们又是如何生成的呢?
欲知后事如何,请听下回分解。>o<
源码


0 0
原创粉丝点击