zoukankan      html  css  js  c++  java
  • java代理模式

    读mybatis源代码时,看到mybatis通过jdk动态代理mapper来实现它的CRUD。因为日常工作中比较少用到代理模式。所以对这一块并不熟悉。

    闲暇之余,翻阅了一些资料和例子了解了一下。做了个demo、记录一点笔记。

    package com.boot.demo.test.proxy;
    
    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    /**
     * @author braska
     * @date 2020/3/13
     **/
    public class ProxyTest {
    
        interface IService {
            void call(String word);
        }
    
        static class ServiceImpl implements IService {
            @Override
            public void call(String word) {
                System.out.println(word);
            }
        }
    
        /**
         * 静态代理
         */
        static class ServiceStaticProxy implements IService {
            private IService service;
            public ServiceStaticProxy(IService service) {
                this.service = service;
            }
    
            @Override
            public void call(String word) {
                System.out.println("static: before call().");
                service.call(word);
                System.out.println("static: after call().");
            }
        }
    
        /**
         * jdk动态代理的方法处理器
         * @param <T>
         */
        static class ServiceHandler<T> implements InvocationHandler {
            private T t;
            public ServiceHandler(T t) {
                this.t = t;
            }
    
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("jdk: before call().");
                Object obj = method.invoke(t, args);
                System.out.println("jdk: after call().");
                return obj;
            }
        }
    
        /**
         * jdk动态代理类
         * @param <T>
         */
        static class ServiceJdkProxy<T> {
            private T t;
            private ServiceHandler handler;
            public ServiceJdkProxy(T t, ServiceHandler handler) {
                this.t = t;
                this.handler = handler;
            }
    
            public T newProxyInstance() {
                return (T)Proxy.newProxyInstance(t.getClass().getClassLoader(), t.getClass().getInterfaces(), handler);
            }
        }
    
        /**
         * cglib动态代理,需引入cglib依赖包
         * @param <T>
         */
        static class ServiceCglibProxy<T> implements MethodInterceptor {
            private T t;
            public ServiceCglibProxy() {}
            public ServiceCglibProxy(T t) {
                this.t = t;
            }
    
            public T newProxyInstance() {
                Enhancer en = new Enhancer();
                en.setSuperclass(t.getClass());
                en.setCallback(this);
                return (T)en.create();
            }
    
            public T newProxyInstance(T t) {
                Enhancer en = new Enhancer();
                en.setSuperclass(t.getClass());
                en.setCallback(this);
                return (T)en.create();
            }
    
            @Override
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                System.out.println("cglib: before call().");
                //Object obj = method.invoke(t, objects);
                Object obj = methodProxy.invokeSuper(o, objects);  //推荐
                System.out.println("cglib: after call().");
                return obj;
            }
        }
    
        public static void main(String[] args) {
            IService service = new ServiceImpl();
            service.call("normal called.");
    
            // static static.
            long time1 = System.currentTimeMillis();
            ServiceStaticProxy staticProxy = new ServiceStaticProxy(service);
            staticProxy.call("static proxy called.");
            System.out.println("静态代理调用时间:" + (System.currentTimeMillis() - time1));
    
            // jdk proxy
            time1 = System.currentTimeMillis();
            ServiceHandler handler = new ServiceHandler(service);
            IService proxyService = new ServiceJdkProxy<>(service, handler).newProxyInstance();
            proxyService.call("jdk proxy called.");
            System.out.println("jdk动态代理调用时间:" + (System.currentTimeMillis() - time1));
    
            // cglib proxy
            time1 = System.currentTimeMillis();
            //IService cgLibProxyService = new ServiceCglibProxy<>(service).newProxyInstance();
            IService cgLibProxyService = new ServiceCglibProxy<IService>().newProxyInstance(service);
            cgLibProxyService.call("cglib proxy called.");
            System.out.println("cglib动态代理调用时间:" + (System.currentTimeMillis() - time1));
    
        }
    }
    

     控制台输出:

    normal called.
    static: before call().
    static proxy called.
    static: after call().
    静态代理调用时间:1
    jdk: before call().
    jdk proxy called.
    jdk: after call().
    jdk动态代理调用时间:8
    cglib: before call().
    cglib proxy called.
    cglib: after call().
    cglib动态代理调用时间:121

    从结果可以看出jdk动态代理整个过程调用耗时远低于gclib动态代理。但这并不能表示jdk性能比cglib动态代理好。事实上,cglib执行速度略快于jdk代理。jdk创建对象的速度远大于cglib,这是由于cglib创建对象时需要操作字节码。cglib执行速度略大于jdk,所以比较适合单例模式。另外由于CGLIB的大部分类是直接对Java字节码进行操作,这样生成的类会在Java的永久堆中。如果动态代理操作过多,容易造成永久堆满,触发OutOfMemory异常。spring默认使用jdk动态代理,如果类没有接口,则使用cglib。

  • 相关阅读:
    Python学习之==>第三方模块的安装、模块导入
    Python学习之==>json处理
    Python学习之==>内置函数、列表生成式、三元表达式
    Python学习之==>函数
    Python学习之==>文件操作
    Python学习之==>集合
    函数,递归,内置函数
    python流程控制
    python文件处理
    Python基础之数据类型
  • 原文地址:https://www.cnblogs.com/braska/p/12486344.html
Copyright © 2011-2022 走看看