mybatis : 静态代理 + jdk动态代理

mybatis : 静态代理 + jdk动态代理

背景

  • 有时目标对象不可直接访问,只能通过代理对象访问
  • 图示:
  • 示例1:房东 ===> 目标对象房屋中介 ===> 代理对象你,我 ===> 客户端对象
  • 示例2:运营商(电信,移动,联通) ===> 目标对象第三方公司 ===> 代理对象开发的应用程序需要发送短信的功能(或者需要支付功能) ===> 客户端对象

代理模式的作用

  • 控制客户对目标对象的访问
  • 增强访问功能

代理模式的分类

静态代理

特点

  • 目标对象和代理对象实现同一个业务接口
  • 目标对象必须实现接口
  • 代理对象在程序运行前就已经存在

静态代理示例与原理分析

业务背景

分析

  • 定义业务接口:面向接口编程,定义业务
  • 目标对象实现接口:业务的核心功能到底怎么实现
  • 代理对象(扩展业务 + 核心业务)实现了目标对象所实现的接口,说明代理对象有资历进行代理对核心业务进行扩展调用目标对象实现核心业务(只能目标对象自己完成)
  • 客户:无法直接访问目标对象,要访问代理对象

代码实现

  • 面向接口编程
    • 成员变量是接口类型
    • 传入目标对象,方法参数设计为接口
    • 调用时,接口指向实现类
  • 静态代理对象代码
  • package com.example.service.impl; import com.example.service.Service; public class Agent implements Service { //定义接口对象 public Service target; public Agent(){} //传入接口对象 public Agent(Service target){ this.target = target; } @Override public void sing() { System.out.println(“协商演出时间……”); System.out.println(“协商演出地点……”); //目标对象完成核心业务,接口指向实现类,调用实现类的方法 target.sing(); System.out.println(“协商演出费用……”); } }

静态代理优缺点

  • 优点:能够灵活地进行目标对象的切换适用于业务固定,目标对象可灵活切换的场景
  • 缺点:无法进行功能的灵活处理,当业务发生改变时,所有涉及到的实现类代码和代理对象代码都要改变

动态代理

JDK动态代理

特点

  • 目标对象必须实现业务接口
  • JDK代理对象不需要实现业务接口
  • JDK代理对象在程序运行前不存在,程序运行时动态的在内存中构建(根据受代理的对象动态创建)
  • JDK动态代理可以灵活的进行业务功能的切换

JDK动态代理用到的类和接口

  • 使用现有的工具类完成JDK动态代理
  • 先了解两个单词的意思InvocationHandler:调用处理程序invoke:调用

Method类

  • 反射时用的类,用来进行目标对象的目标方法的反射调用
  • method对象,接住我们正在调用的方法 sing(),show()method == sing(),show(),即:待调用的方法method.invoke() ==> 相当于手工调用目标方法 sing(),show();

InvocationHandler接口

  • 用来实现代理和业务功能,我们在调用时使用匿名内部实现匿名内部实现:new接口的同时,重写接口中的方法(相当于定义了该接口的一个实现类)

Proxy类

  • 位于:java.lang.reflect.Proxy包下
  • 有一个核心方法:Proxy.newProxyInstance(….),专门获取动态代理对象,有三个参数
    • 参数1:ClassLoader loader
      • 目标对象的类加载器
      • 目的:获取类方法等信息,毕竟底层还是要调用受代理对象所实现的方法
      • 传入:targetObj.getClass().getClassLoader();
    • 参数2:Class[] interfaces
      • 目标对象实现的所有接口,类的接口可以有多个
      • 目的:获取目标对象实现的所有接口以及接口的相关信息,毕竟底层要知道目标对象都可以完成哪些业务操作
      • 传入:targetObj.getClass().getInterfaces();
    • 上面两个参数为代理对象动态的创建和调用目标对象的方法提供了数据支持,第3个参数相当于调用程序
    • 参数3:InvocationHandler
      • 实现代理功能的接口,这里代理功能包括:扩展的功能 + 核心业务功能,传入的匿名内部实现如下
    • new InvocationHandler() { @Override public Object invoke( Object obj, //用来反射调用方法 Method method, //待调用方法需要的参数 Object[] args) throws Throwable { //扩展业务 System.out.println(“协商演出时间……”); System.out.println(“协商演出地点……”); //核心业务,具体调用什么方法根据外层业务来反射调用对应方法 Object res = method.invoke(target, args); //扩展业务 System.out.println(“协商演出费用……”); //目标对象执行的目标方法的返回值 return res; } }

JDK动态代理示例

  • 代理工厂代码
  • package com.example.proxy; import com.example.service.Service; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class ProxyFactory { //目标对象 Service target; public ProxyFactory(){} public ProxyFactory(Service target){ this.target = target; } //返回代理对象 public Object getAgent(){ return Proxy.newProxyInstance( //需要知道受代理对象的类信息 target.getClass().getClassLoader(), //需要知道受代理对象实现的所有接口信息 target.getClass().getInterfaces(), //反射调用目标对象的目标方法 new InvocationHandler() { @Override public Object invoke( Object obj, //用来反射调用方法 Method method, //待调用方法需要的参数 Object[] args) throws Throwable { //扩展业务 System.out.println(“协商演出时间……”); System.out.println(“协商演出地点……”); //核心业务,具体调用什么方法根据外层业务来反射调用对应方法 Object res = method.invoke(target, args); //扩展业务 System.out.println(“协商演出费用……”); //目标对象执行的目标方法的返回值 return res; } } ); } }
  • 测试代码示例
  • package com.example.proxy; import com.example.service.Service; import com.example.service.impl.SuperStarZhou; import org.junit.Test; public class TestProxyFactory { @Test public void testGetProxy(){ //确定客户需求 ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); //根据需求动态返回对应类型的代理对象 Service agent = (Service) factory.getAgent(); //依托对应类型的动态代理对象完成业务:扩展业务(动态代理对象完成) + 核心业务(目标对象完成) agent.sing(); } @Test public void testGetProxy2(){ ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); Service agent = (Service) factory.getAgent(); String res = (String) agent.show(60); System.out.println(res); } }

注意

  • 可被代理的方法应该是受代理对象实现的所有接口中的方法与其所有实体方法的交集
    • 本类中独有的方法不被代理
  • 类型的转变
  • @Test public void testGetProxy2() { ProxyFactory factory = new ProxyFactory(new SuperStarZhou()); Service agent = (Service) factory.getAgent(); Service liu = new SuperStarLiu(); System.out.println(“类型1: ” + liu.getClass()); System.out.println(“类型2: ” + agent.getClass()); } /* 输出结果: 类型1: class com.example.service.impl.SuperStarLiu 类型2: class com.sun.proxy.$Proxy7 */
郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年8月11日
下一篇 2022年8月11日

相关推荐

  • 天魔再临活动中如何花最少点券快速抽取到限定皮肤呢?看完学到了

    在前几天,官方正式开启了天魔再临这个活动,在此活动中,小伙伴们有几率抽取到返场的天魔缭乱以及奇迹圣诞,这两款皮肤质量都是十分不错的,尤其是天魔缭乱经过前几年的一波重做,现如今都快堪…

    2022年8月20日
  • B2B CRM的核心模块:营销自动化

    营销自动化是CRM的核心模块之一,该模块主要是通过营销活动获取更多的销售线索,并对线索进行转化和分配的过程管理。想做好营销自动化,下面五点是必须要具备的,而且还需要做精、做细: 一…

    2022年6月12日
  • 大疆Pocket 2云台相机又升级!防抖高清迷你小巧,跑着拍也能很稳

    随着智能手机拍照功能升级,让越来越多的人养成一个习惯,甭管是美食,美景,还是好玩的事情,都希望用手机拍照,拍视频的方式来记录,而当年高大上的单反相机,没能迎来大面积的普及,就因为智…

    2022年6月25日
  • 「双语太空播报」NASA的飞马号将携阿尔忒弥斯一号火箭硬件

    NASA的Pegasus驳船为该机构位于佛罗里达州的肯尼迪航天中心绘制了航向图,其中载有航天发射系统(SLS)火箭的Artemis I核心级。核心级将提供200多万磅的推力,帮助发…

    2022年8月16日
  • 分享3种用手机赚钱的方法(手机赚钱的方法有哪些)

    手机赚钱方法其实有许多,其实你的手机就是一台自动提款机,只要你熟悉种种手机赚钱的项目操作,能够坚持在这一领域之中辛勤耕耘,那么你的手机自然就能为你提供一笔笔可观的经济收入,那么简单…

    2022年10月19日
  • 知三当三,恃靓行凶,李嘉欣真是个狠人

    前半生游走在各类花边新闻里,美貌与骂名齐飞。 知三当三,恃靓行凶,嚣张,“逼走正宫”,私德有亏,在流言蛮语中转了一圈,依然能全身而退。 目标清晰,内心强大,李嘉欣确实是个狠人。 李…

    2022年9月23日
  • 电脑怎么给文件夹加密并隐藏起来?

    在自己的电脑上,肯定会有一些重要的文件是不希望被他人随意访问的。那么如何保护好自己的文件,不被他人查看呢?最好的方法那自然是给文件夹加上密码啦,本文分享一个既能够保证文件不被打开并…

    2022年6月24日
  • 军事仿真龙头企业华如科技今日挂牌上市

    本报记者 向炎涛 见习记者 许林艳 6月23日,华如科技登陆A股资本市场,为企业下一步的发展奠定了坚实的基础,同时也开启了企业发展的新篇章。 北京华如科技股份有限公司(股票简称“华…

    2022年6月24日
  • 计算机行业IT面试题第1期

    了解哪些开源的rpc框架?dubbo的调用过程简单说一下? 1、RMI,远程方法调用;2、Hessian,基于HTTP的远程方法调用;3、Dubbo支持多种协议 dubbo调用过程…

    2022年6月16日
  • 炬光科技研究报告:进军车载激光雷达的光子专家

    (报告出品方/作者:申万宏源研究,杨海燕,朱型檑,李蕾,黄婷) 1. 尝试运营优化的光子上游专家 1.1 立足激光上游传统业务,进军中游 炬光科技所属行业为激光行业,起家于上游元器…

    2022年6月13日

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息