JDK代理

1,代理模式

代理模式是指,为其他对象提供一种代理控制这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。

换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强业务逻辑。

**客户类真正的想要访问的对象是目标对象,但是客户类真正可以访问的对象是代理对象。**客户类对目标对象的访问是通过访问代理对象来实现的。当然,代理类与目标类要实现同一个接口。

例如: 有 A,B,C 三个类, A 原来可以调用 C 类的方法, 现在因为某种原因 C 类不允许 A 类调用其方法,但 B 类可以调用 C 类的方法。A 类通过 B 类调用 C 类的方法。这里 B 是 C 的代理。 A 通过代理 B 访问 C.

Window 系统的快捷方式也是一种代理模式。快捷方式代理的是真实的程序,双击快捷 方式是启动它代表的程序。

2,使用代理模式的作用

1,功能增强: 在你原有的功能基础上,增加了额外的功能,新增加的功能,叫做功能增强。

​ 功能增强的三种方式:

​ 1,增强参数列表。

​ 2,增强返回值类型。

​ 3,增强方法体执行逻辑。

2,控制访问: 代理类不让你访问目标类,例如商家不让客户访问厂家。

3,实现代理的方式

实现代理的方式分为:静态代理,动态代理

3.1,静态代理

3.1.1,静态代理概念

静态代理是指,代理类在程序运行前就已经定义好.java源文件,其与目标类的关系在程序运行前就已经确立。在程序运行前,代理类已经编译为.class文件。

(1)代理类是自己实现的,自己创建一个java类,表示代理类。

(2)同时你所要代理的目标类是确定的。

3.1.2,静态代理的优缺点

(1)优点:

​ 1,容易理解

​ 2,实现简单

(2)缺点:

​ 当你的项目中,目标类和代理类很多的时候有以下缺点:

1,代码复杂,难于管理

​ 代理类和目标类实现了相同的接口,每个代理类都需要实现目标类的方法,这样就出现了大量的代码重复。如果接口中增加 了一个方法,处理目标类需要实现这个方法外,所有代理类也需要实现这个方法。增加了代码维护的复杂度。

2,代理类依赖目标类,代理类过多

​ 代理类只服务于一种类型的目标类,如果要服务多个类型,势必要为每一种目标类都创建代理类,静态代理在程序规模稍 大时就无法胜任了。代理数量过多。

3.1.3,静态代理的实现步骤

(1)定义业务接口

​ 定义业务接口,其中含有抽象方法,该抽象方法是目标方法**。**

(2)定义接口实现类(目标类)

​ 目标类实现了业务接口。

(3)定义代理类

​ 代理类也实现了业务接口,并在其中访问目标类。

(4)客户端调用者

​ 使用代理类,访问目标类。

3.2,动态代理

3.2.1,动态代理的概念

动态代理是值代理对象在程序运行时由JVM根据反射机制动态生成的。动态代理不需要定义代理类的.java源文件。

动态代理其实就是在jdk运行期间,动态创建class字节码并加载到JVM

总结:动态代理就是在程序组执行过程中,使用jdk的反射机制,创建一个代理类,并动态地指定代理目标类。

在静态代理中目标类很多的时候,可以使用动态代理,避免静态代理的缺点。(动态代理中,即使目标类很多,1,代理类数量可以很少;2,当你修改接口中的方法时,不会影响代理类)

3.2.2,动态代理的分类

动态代理的实现方式分为两类:

**(1)jdk动态代理(理解):**使用java反射包中的类和接口实现动态代理的功能。

​ 反射包java.lang.reflect里面有三个类:invocationHandler,Method,Proxy。

**(2)cglib动态代理(了解):**cglib是第三方的工具库,创建代理对象。

​ cglib的原理是继承,cglib通过继承目标类,在子类中重写父类中同名的方法,实现功能的修改。

​ 因为cglib是继承,重写方法,所以要求目标类不能是final的,方法也不能是final的。

​ cglib的要求目标类比较宽松,只要能够继承就行。cglib在很多框架中使用,比如mybatis,spring

3.2.3,jdk的动态代理

1,概念:jdk动态代理是基于Java的反射机制实现的。使用jdk中接口和类山西爱你代理对象的动态穿建。

​ jdk的动态要求目标对象必须实现接口,这是java设计上的要求(代理对象必须和目标对象实现相同的接口)

2,从jdk1.3以来,java语言通过java.lang.reflect包中提供的三个类来支持代理模式:Proxy,Method,InovcationHandler。

(1)InvocationHandler接口

​ InvocationHandler接口叫做调用处理器,负责完成完成调用目标方法,并增强功能。

​ 通过代理对象执行目标接口中的方法,会把方法的调用分派给调用处理器的实现类,执行实现类中的invoke()方法,我们 需要把功能代理写在invoke()方法中。

​ 接口中只有一个方法:

         public Object invoke(Object proxy,Method method,Object[] args)throws Throwable;

​ 在invoke方法中可以街区对目标方法的调用。在这里可以进行功能增强。Java的动态代理是建立在反射机制之上的。

​ 实现了InvocationHandler接口的类**用于加强目标类的业务逻辑。**具体加强逻辑的代码定义在invoke方法中,通过代理对象执 行接口中的方法时,会自动调用invoke()方法。

​ invoke方法的介绍如下:

​ 参数:

​ 1,Proxy proxy :jdk创建的代理对象,无需赋值。

​ 2,Method method:目标类中的方法,jdk提供

​ 3,Object[] args:目标类中方法的参数,jdk提供。

(2)Method 类

​ invoke()方法的第二个参数为Method类对象,该类有一个方法也叫invoke(),可以调用目标方法,这两个invoke()方法虽 然同名,但无关。

     public Object invoke ( Object obj, Object... args)

​ 参数:

​ 1,Object obj :代表目标对象

​ 2,args:表是目标方法的参数,就是其上一层invoke方法的第三个参数。

​ 该方法的作用是:调用执行 obj 对象所属类的方法,这个方法由其调用者 Method 对象确定。

(3)Proxy类

​ 通 过 JDK 的 java.lang.reflect.Proxy 类 实 现 动 态 代 理 , 会 使 用 其 静 态 方 法 newProxyInstance(),依据目标对象、业务 接口及调用处理器三者,自动生成一个动态代理对象。

     public static newProxyInstance ( ClassLoader loader, Class<?>[] interfaces, InvocationHandler                 handler)

​ 参数:

​ 1,ClassLoader loader: 目标类的类加载器,通过目标对象的反射可获取。

​ 一般使用:

         真实对象.getClass().getClassLoader();

​ 2,Class <?> interfaces:目标类实现的接口数组,通过目标对象的反射可获取。

​ 一般使用:

         真实对象.getClass().getInterfaces();

​ 3,InvocationHandler handler:调用处理器。

​ 一般使用匿名内部类,在invoke()方法中增强方法。new InvocationHandler();

3.2.4,jdk动态代理的实现

jdk 动态代理是代理模式的一种实现方式,其只能代理接口。

实现步骤:

1,新建一个接口,作为目标接口。

2,为接口创建一个实现类,是目标类。

3,创建类实现java.lang.reflect.InvocationHandler 接口,调用目标方法并增加其他功能代码。(可以使用匿名内部类)

4,创建动态代理对象,使用Proxy.newProxyInstance()方法,并把返回值强制转为接口类型。

具体实现:

(1)定义目标接口

package 动态代理;
//目标接口
public interface UsbSell {float sell(int amount);
}

(2)实现目标接口实现类

package 动态代理.Factory;import 动态代理.UsbSell;
//金士顿厂商
//目标类
public class UsbKingFactory implements UsbSell {@Overridepublic float sell(int amount) {return 20*amount;}
}

(3)定义调用处理程序 (4)创建动态代理对象

package 动态代理.Shop;import 动态代理.Factory.UsbKingFactory;
import 动态代理.UsbSell;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class TaoBao {public static void main(String[] args) {//创建代理对象,使用Proxy//1,创建目标对象UsbSell king=new UsbKingFactory();//2,创建代理对象//使用匿名内部类的形式创建InvocationHandler对象UsbSell proxy = (UsbSell) Proxy.newProxyInstance(king.getClass().getClassLoader(), king.getClass().getInterfaces(), new InvocationHandler() {//重写invoke方法。@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//向厂家发送订单,即调用厂家的sell方法Object res = method.invoke(king, args);//进行功能增强float price=0;if(res!=null){price=(float)res+20;}//增加其他功能System.out.println("恭喜您,获得10元优惠券");return price;}});//使用代理对象执行方法float price = proxy.sell(1);System.out.println("通过动态代理对象,调用方法:"+price);}}

3.2.5,动态代理的作用

可以在不改变原来目标方法功能的前提下, 可以在代理中增强自己的功能代码。
程序开发中的意思。
比如:你所在的项目中,有一个功能是其他人(公司的其它部门,其它小组的人)写好的,你可以使用。
GoNong.class , GoNong gn = new GoNong(), gn.print();

你发现这个功能,现在还缺点, 不能完全满足我项目的需要。 我需要在gn.print()执行后,需要自己在增加代码。
用代理实现 gn.print()调用时, 增加自己代码, 而不用去改原来的 GoNong文件。

增强功能一般的使用方法

**1,增强参数:**可以通过args获取参数,修改之后再传给Method. invoke()方法。

2,增强返回值类型:在return中修改

**3,增强方法体:**在invoke方法中修改逻辑

注意:可以在invoke()方法中,判断方法名,给不同的方法不同的增强。

4,cgLib 代理

CGLIB(Code Generation Library)是一个开源项目。是一个强大的,高性能,高质量的 Code 生成类 库,它可以在运行期扩展 Java 类与实现 Java 接口。它广泛的被许多 AOP 的框架使用,例如 Spring AOP。 使用 JDK 的 Proxy 实现代理,要求目标类与代理类实现相同的接口。若目标类不存在 接口,则无法使用该方式实现。 但对于无接口的类,要为其创建动态代理,就要使用 CGLIB 来实现。CGLIB 代理的生成 原理是生成目标类的子类,而子类是增强过的,这个子类对象就是代理对象。所以,使用 CGLIB 生成动态代理,要求目标类必须能够被继承,即不能是 final 的类。 cglib 经常被应用在框架中,例如 Spring ,Hibernate 等。Cglib 的代理效率高于 Jdk。对 于 cglib 一般的开发中并不使用。做了一个了解就可以。

JDK代理模式学习笔记相关推荐

  1. 设计模式之代理模式学习笔记

    前言 代理模式,也叫做委托模式.就好比请律师打官司一样,为其他对象提供一种代理,来控制对这个对象的访问. 结构图 接下来我们对以上结构图拆解,进行角色分析: 1.Subject:抽象主题类,声明真实主 ...

  2. java代理模式学习笔记

    代理模式:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理类和被代理类必须实现同一个接口 ...

  3. Windows保护模式学习笔记(十四)—— 阶段测试

    Windows保护模式学习笔记(十四)-- 阶段测试 题目一 解题步骤 题目二 解题步骤 题目一 描述:给定一个线性地址,和长度,读取内容 int ReadMemory(OUT BYTE* buffe ...

  4. Windows保护模式学习笔记(十三)—— PWTPCD

    Windows保护模式学习笔记(十三)-- PWT&PCD 要点回顾 CPU缓存 CPU缓存与TLB的区别 PWT(Page Write Through) PCD(Page Cache Dis ...

  5. Windows保护模式学习笔记(十二)—— 控制寄存器

    Windows保护模式学习笔记(十二)-- 控制寄存器 控制寄存器 Cr0寄存器 Cr2寄存器 Cr4寄存器 控制寄存器 描述: 控制寄存器有五个,分别是:Cr0 Cr1 Cr2 Cr3 Cr4 Cr ...

  6. Windows保护模式学习笔记(十)—— TLB

    Windows保护模式学习笔记(十)-- TLB 地址解析 10-10-12分页 2-9-9-12分页 TLB TLB结构 TLB种类 练习1:体验TLB的存在 第一步:运行代码 第二步:设置中断门描 ...

  7. Windows保护模式学习笔记(九)—— 2-9-9-12分页

    Windows保护模式学习笔记(九)-- 2-9-9-12分页 要点回顾 10-10-12分页 原理 环境配置 2-9-9-12分页 原理 PDPTE PDE PTE XD/NX标志位 环境配置 实验 ...

  8. Windows保护模式学习笔记(八)—— 页目录表基址/页表基址

    Windows保护模式学习笔记(八)-- 页目录表基址/页表基址 要点回顾 一.页目录表基址 实验:拆分线性地址C0300000,并查看其对应的物理页 第一步:打开一个进程,获得它的Cr3 第二步:查 ...

  9. Windows保护模式学习笔记(七)—— PDEPTE

    Windows保护模式学习笔记(七)-- PDE&PTE Cr3 PDE(页目录表项) PTE(页表项) 物理页的属性 10-10-12分页的补充 实验1:证明PTE的特征1 第一步:选择一个 ...

最新文章

  1. Unity初学Shadergraph创建着色器学习教程
  2. instanceof, isinstance,isAssignableFrom的区别
  3. shell实例第10讲:判断用户输入的是否为数字
  4. integral函数
  5. 直播预告丨B2B 企业如何高效获客增长?
  6. Linux wget命令用法详解
  7. 软件工程之个人项目--词频统计
  8. 如何解开机器学习的面纱?
  9. 深度学习中 epoch,[batch size], iterations概念解释
  10. 解决子元素和父元素同时触发onclick
  11. (195)FPGA上电后IO的默认状态(ISE软件默认为1)
  12. refs win10_Win10PE版本改为专业工作站版开启refs支持工具
  13. 程序员菜鸟到高手的11个阶段,你处于哪个阶段?
  14. PHP环境 PDOException PDOException: could not find driver
  15. Gradle 命令之 --stacktrace , --info , --debug 用法
  16. MySQL的条件判断函数
  17. 缺陷检测End-to-end training of a two-stage neural networkfor defect detection(端到端的两步神经网络的缺陷检测)
  18. 视频管理系统源码php,video cms 视频分享管理系统
  19. 如果你恨一个人...
  20. SAP FICO 如何看一个总账科目的修改记录?

热门文章

  1. 插入区间之非合并区间的思路 leetcode57
  2. 用sublime搭建基于GoSublime+gocode+MarGo的下载SublimeGO开发环境
  3. [GO]学习新语言之卡塔练习--猜数字
  4. iOS中ImageIO框架详解与应用分析
  5. Django电商项目(八)订单生成、悲观锁、乐观锁
  6. 用 Jupyter Notebook 爬取微博图片保存本地!
  7. linux cpu使用率计算
  8. Python调用百度AI识别身份证
  9. Tushare如何获取股票历史交易数据
  10. java怎么处理黑白bmp_Android JNI处理图片实现黑白滤镜的方法