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

    心有多大,天有多高,一起奋斗!!
  • 相关阅读:
    TDengine在上海电气储能智慧运维系统中的应用
    一文带你理解TDengine中的缓存技术
    taosAdapter正式发布:支持从OpenTSDB向TDengine无缝迁移
    TDengine 在中节能风力发电运维系统中的落地实践
    格创东智选择 TDengine,实现海量数据实时全生命周期管理
    TDengine 在水电厂畸变波形分析及故障预判系统中的应用
    使用wireshark抓包分析TCP三次握手
    K8s中 蓝绿部署、金丝雀发布、滚动更新汇总
    K8s运维锦囊,19个常见故障解决方法
    一次由 Kubernetes HostPort 引发的服务故障排错记实
  • 原文地址:https://www.cnblogs.com/zhaolei1996/p/12423837.html
Copyright © 2011-2022 走看看