zoukankan      html  css  js  c++  java
  • Java笔记(二十一) 动态代理

    动态代理

    一、静态代理

    代理的背后一般至少有一个实际对象,代理的外部功能和实际对象一般是一样的,

    用户与代理打交道,不直接接触实际对象。代理存在的价值:

    1)节省成本比较高的实际对象创建开销,按需延迟加载,创建代理时

    并不正真创建实际对象,而只是保存实际对象的地址,在需要时再加载或者创建。

    2)执行权限检查,代理检查权限后再调用实际对象。

    3)屏蔽网络的差异性和复杂性,代理在本地,而实际对象在其他服务器上,调用

    本地代理时,本地代理请求其他服务器。

    静态代理示例:

    public class SimpleStaticProxy {
        //服务接口
        static interface IService {
            void sayHello();
        }
        //服务类
        static class RealService implements IService {
            @Override
            public void sayHello() {
                System.out.println("hi");
            }
        }
        //代理类
        static class TraceProxy implements IService {
            private IService realService;
    
            public TraceProxy(IService realService) {
                this.realService = realService;
            }
    
            @Override
            public void sayHello() {
                System.out.println("Start say hi");
                realService.sayHello();
                System.out.println("End say hi");
            }
        }
    
        public static void main(String[] args) {
            RealService service = new RealService();
            TraceProxy traceProxy = new TraceProxy(service);
            traceProxy.sayHello();
        }
    }

    静态代理缺陷:如果每个类都需要代理,我们需要为每个类都创建代理类,

    实现所有接口,这个工作量相当大。

    二、Java SDK代理

    所谓动态代理,代理类是动态生成的。

    1.用法

    public class SimpleJDKDynamicProxy {
        interface IService {
            void sayHello();
            void sayGoodBye();
        }
        static class RealService implements IService {
            @Override
            public void sayHello() {
                System.out.println("hi");
            }
            @Override
            public void sayGoodBye() {
                System.out.println("GoodBye world!");
            }
        }
        static class SimpleInvocateHandler implements InvocationHandler {
            private Object realObj;
            public SimpleInvocateHandler(Object realObj) {
                this.realObj = realObj;
            }
            /**
            * @param proxy 表示代理对象本身,注意它不是被代理的对象,这个参数用处不大
            * @param method 表示正在被调用的方法
            * @param args 表示方法的参数
            * */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Start " + method.getName());
                Object result = method.invoke(realObj, args);
                System.out.println("End " + method.getName());
                return result;
            }
        }
        public static void main(String[] args) {
            IService realService = new RealService();
            IService proxyService = (IService) Proxy.newProxyInstance(IService.class.getClassLoader(),
                    new Class<?>[]{IService.class}, new SimpleInvocateHandler(realService));
            proxyService.sayHello();
            proxyService.sayGoodBye();
        }
    }
    /**
        * @param loader 类加载器
        * @param interfaces 代理类要实现的接口列表
        * @param h 该接口定义了invoke方法,对代理接口所有的方法调用都会转给该方法
        * @return 可以转换为interfaces数组中的某个接口类型,注意只能转换为接口不能转换为具体的类
        * */
        public static Object newProxyInstance(ClassLoader loader,
                                              Class<?>[] interfaces, InvocationHandler h);

    2.基本原理

    创建proxyService的代码可以用如下的代码代替:

    //创建代理类定义,类定义会被缓存
    Class<?> proxyCls = Proxy.getProxyClass(IService.class.getClassLoader(), new Class<?>[] { IService.class });
    //获取代理类的构造方法
    Constructor<?> ctor = proxyCls.getConstructor(new Class<?>[] { InvocationHandler.class });
    InvocationHandler handler = new SimpleInvocationHandler(realService);
    //创建代理类对象
    IService proxyService = (IService) ctor.newInstance(handler);
        final class $Proxy0 extends Proxy implements SimpleJDKDynamicProxyDemo.IService {
            private static Method m1;
            private static Method m3;
            private static Method m2;
            private static Method m0;
            public $Proxy0(InvocationHandler paramInvocationHandler) {
                super(paramInvocationHandler);
            }
            public final boolean equals(Object paramObject) {
                return((Boolean) this.h.invoke(this, m1,
                        new Object[] { paramObject })).booleanValue();
            }
            public final void sayHello() {
                this.h.invoke(this, m3, null);
            }
            public final String toString() {
                return (String) this.h.invoke(this, m2, null);
            }
            public final int hashCode() {
                return ((Integer) this.h.invoke(this, m0, null)).intValue();
            }
            static {
                m1 = Class.forName("java.lang.Object").getMethod("equals",
                        new Class[] { Class.forName("java.lang.Object") });
                m3 = Class.forName(
                        "laoma.demo.proxy.SimpleJDKDynamicProxyDemo$IService")
                        .getMethod("sayHello",new Class[0]);
                m2 = Class.forName("java.lang.Object")
                        .getMethod("toString", new Class[0]);
                m0 = Class.forName("java.lang.Object")
                        .getMethod("hashCode", new Class[0]);
            }
        }

    三、cglib动态代理

    Java SDK动态代理的局限,它只能为接口创建代理,返回的代理对象也只能转换到某个接口类型。

    public class SimpleCGLibDemo {
        static class RealService {
            public void sayHello() {
                System.out.println("hello");
            }
        }
        static class SimpleInterceptor implements MethodInterceptor {
            @Override
            public Object intercept(Object object, Method method, Object[] args,
                                    MethodProxy methodProxy) throws Throwable {
                System.out.println("start " + method.getName());
                Object result = methodProxy.invokeSuper(object, args);
                System.out.println("end " + method.getName());
                return result;
            }
        }
        private static <T> T getProxy(Class<T> cls) {
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(cls);
            enhancer.setCallback(new SimpleInterceptor());
            return (T) enhancer.create();
        }
        public static void main(String[] args) {
            RealService proxy = getProxy(RealService.class);
            proxy.sayHello();
        }
    }

    cglib是通过继承实现的,具体原理略。

  • 相关阅读:
    excel表中的一列,如何去除重复项
    Notepad++ 列操作
    mysql 登陆其它服务器
    贪心算法处理背包问题
    分治法处理排序问题
    回溯法_皇后问题
    动态规划算法的java实现
    人事管理系统
    java复习笔记
    核心动画-翻页效果的实现
  • 原文地址:https://www.cnblogs.com/Shadowplay/p/10005222.html
Copyright © 2011-2022 走看看