设为首页 加入收藏

TOP

9、Spring之代理模式(三)
2023-08-26 21:11:22 】 浏览:92
Tags:Spring
invoke方法来统一管理代理类中的方法该如何执行,该方法有三个参数 /** * @param proxy:表示代理对象 * @param method:表示要执行的方法 * @param args:表示要执行的方法的参数列表 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //在调用目标对象执行功能之前,加入额外的操作(这里是附加日志功能) System.out.println("[日志] "+method.getName()+" 方法开始了,参数是:" + Arrays.toString(args)); //固定写法:调用目标对象实现的核心逻辑(最重要的步骤) Object result = method.invoke(target, args); //在调用目标对象执行功能之后,加入额外的操作(这里是附加日志功能) System.out.println("[日志] "+method.getName()+" 方法结束了,结果是:" + result); //固定写法:保证代理对象和目标对象的返回值一致 return result; } }; //返回(java.lang.reflect包下的)Proxy类的newProxyInstance方法所生产的代理对象 /** * newProxyInstance方法有三个参数: * * 1、ClassLoader classLoader:指定加载(动态生成的)代理类的类加载器 * 类只有被加载后才能使用,(动态生成的)代理类需要用应用类加载器来加载 * 类加载器有四种: * 跟类加载器(用于加载核心类库) * 扩展类加载器(用于加载扩展类库) * 应用类加载器(用于加载自己写的类或第三方jar包中的类) * 自定义类加载器 * * 2、Class<?>[] interfaces:指定代理对象要实现的接口 * 这个参数用于保证代理对象和目标对象有相同的方法列表 * * 3、InvocationHandler invocationHandle:指定调用处理器 * 该处理器设置了代理对象实现的接口的方法被调用时,该如何执行 */ return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler); } }

9.6.2、测试

image

    @Test
    public void testDynamicProxy(){

        //根据目标对象来创建(动态)代理对象的工厂
        ProxyFactory proxyFactory = new ProxyFactory(new CalculatorImpl());

        //通过(动态)代理对象的工厂,生成目标对象所对应的(动态)代理对象
        //因为代理类是动态生成的,所以不确定代理类的类型,因此用其所实现的接口类型
        Calculator poxy = (Calculator) proxyFactory.getPoxy();

        //调用动态代理对象的方法,该方法是目标对象核心业务方法的增强方法
        int addResult = poxy.add(1, 2);
        System.out.println(addResult);

    }

9.6.3、增强的位置

除了可以在调用目标对象执行功能之前或之后,加入额外的操作之外;

还可以在调用目标对象执行功能发生异常时(catch位置)或在调用目标对象执行功能完毕时(finally位置),加入额外的操作

也就是说,(静态或动态)代理能增强的位置一共有四个

            //通过invoke方法来统一管理代理类中的方法该如何执行,该方法有三个参数
            /**
             * @param proxy:表示代理对象
             * @param method:表示要执行的方法
             * @param args:表示要执行的方法的参数列表
             */
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object result = null;
                try {
                    //第1个增强位置:在调用目标对象执行功能之前,加入额外的操作(这里是附加日志功能)
                    System.out.println("[日志] "+method.getName()+" 方法开始了,参数是:" + Arrays.toString(args));

                    //固定写法:调用目标对象实现的核心逻辑(最重要的步骤)
                    result = method.invoke(target, args);

                    //第2个增强位置:在调用目标对象执行功能之后,加入额外的操作(这里是附加日志功能)
                    System.out.println("[日志] "+method.getName()+" 方法结束了,结果是:" + result);
                } catch (Exception e) {
                    //第3个增强位置:在调用目标对象执行功能发生异常时,加入额外的操作(这里是附加日志功能)
                    System.out.println("[日志] "+method.getName()+",异常:"+e.getMessage());
                }  finally {
                    //第4个增强位置:在调用目标对象执行功能完毕时,加入额外的操作(这里是附加日志功能)
                    System.out.println("[日志] "+method.getName()+",方法执行完毕");
                }

                //固定写法:保证代理对象和目标对象的返回值一致
                return result;
            }

9.6.4、扩展知识

  • 动态代理有两种方式:jdk动态代理(本示例)和cglib动态代理

  • jdk动态代理,要求目标必须实现接口,而且只能对目标所实现的接口方法进行增强

  • jdk动态代理,生成的代理类在com.sun.proxy包下,类名为:$proxy+数字

  • cglib动态代理,不要求目标必须实现接口,生成的代理类会继承目标类,并且和目标类在相同的包下

  • 虽然在实际中很少写动态代理的代码,但了解动态代理的思想,对学习Spring的AOP知识很有帮助

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Java 中的 7 种重试机制,还有谁.. 下一篇切面实现下单请求防重提交功能(..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目