zoukankan      html  css  js  c++  java
  • 动态代理

    常见的动态代理实现主要有两种方法:

    一、jdk动态代理,被代理对象必须是基于接口,使用Proxy中的newProxyInstanc()方法

    二、cglib动态代理,被代理类不能是最终类(final修饰的类),因为cglib实现的动态代理是基于子类实现的,需要引入第三方jar包cglib,cglib依赖asm,使用EnHancer.create()方法,代码中有介绍

    jdk生成动态代理的类:

    public class ProxyTool {
    
        /**
         *  需要被代理的类
         */
        private Object obj;
        public ProxyTool(Object obj){
            this.obj = obj;
        }
    
        /**
         * Proxy.newProxyInstance()方法有三个参数:
         * ClassLoader:用于加载代理对象的字节码,与被代理对象的类加载器保持一致,固定写法
         * Class[]:字节码数据,用于让代理类与被代理类有相同的方法,固定写法
         * InvocationHandler: 用于提供增强的代码,InvocationHandler接口中有一个方法 invoke()
         *
         *
         * invoke中有三个参数:
         * proxy:代理对象
         * method:当前执行的方法
         * args:当前执行方法的参数
         * @return
         */
        public Object getProxy(){
            return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),
                    new InvocationHandler() {
                        public Object invoke(Object proxy, Method method, Object[] args) throws InvocationTargetException, IllegalAccessException {
                           //写增强代码的地方
                            System.out.println("动态代理生效");
                            return method.invoke(obj,args);
                        }
                    });
    
        }
    }
    View Code

    cglib生成动态代理:

    public class CglibProxy {
        /**
         * 被代理对象
         */
        private Object obj;
        public CglibProxy(Object obj){
            this.obj = obj;
        }
    
        /**
         * 获取代理对象方法
         * 使用cglib中Enhancer.create()方法,
         * create()方法有两个参数
         * Class:字节码,被代理对象的字节码
         * Callback;用于写增强代码的接口,一般用其子接口MethodInterceptor
         *
         *
         * @return
         */
        public Object getProxy(){
            return Enhancer.create(obj.getClass(), new MethodInterceptor() {
                /**
                 *注意:intercept()方法中形参的名称o是指代理对象
                 * @param o      代理对象
                 * @param method  当前执行的方法
                 * @param objects  当前执行方法的参数
                 * @param methodProxy  当前执行方法的代理对象
                 * @return
                 * @throws Throwable
                 */
                public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                    //写增强的代码
                    System.out.println("动态代理开启,这是cglib代理");
                    return method.invoke(obj,objects);
                }
            });
    
        }
    }
    View Code

    测试类:

    public class Main {
        public static void main(String[] args) {
            //被代理对象
            IProxyImpl proxy1 = new IProxyImpl();
            //代理工具
            //ProxyTool ProxyTool = new ProxyTool(proxy1);
            CglibProxy cglibProxy = new CglibProxy(proxy1);
            //获取到代理类,当为jdk代理时不能用用实现类来强转
            IProxy proxy = (IProxy)cglibProxy.getProxy();
    
            //执行方法
            proxy.print();
        }
    }
    View Code

     使用动态代理时,若被代理的方法抛出异常,代理对象也会抛出异常,但是异常不是原来的异常;

     该异常可参考这篇文章:https://www.cnblogs.com/zhaolei1996/p/12435256.html

    心有多大,天有多高,一起奋斗!!
  • 相关阅读:
    [编程] 正则表达式
    [游戏] PhysX物理引擎(编程入门)
    [PHP] visitFile()遍历指定文件夹
    [D3D] 用PerfHUD来调试商业游戏
    [C,C++] 妙用0元素数组实现大小可变结构体
    [D3D] DirectX SDK 2006学习笔记1——框架
    [JS] 图片浏览器(兼容IE,火狐)
    [C#(WinForm)] 窗体间传值方法
    [ASP.NET] 提示错误:The server has encountered an error while loading an application during the processing your request
    [JS] 火狐得到文件的绝对路径(暂时的方法)
  • 原文地址:https://www.cnblogs.com/zhaolei1996/p/12423837.html
Copyright © 2011-2022 走看看