• 动态代理


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

    一、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

    心有多大,天有多高,一起奋斗!!
  • 相关阅读:
    ASP.NET 概述
    用vs调试项目页面无样式
    eniac世界第二台计算机
    汇编语言
    操作系统发展史
    网站架构发展
    简单分布式系统构建知识
    Android常用adb命令
    USB 3.0规范中译本 第4章 超高速数据流模型
    ECMAScript 6 &ECMAScript 5(在线手册)
  • 原文地址:https://www.cnblogs.com/zhaolei1996/p/12423837.html
Copyright © 2020-2023  润新知