前言

代理是什么

事故现场:我家的宠物今天生病了,而我又没有相关的医学知识,所以我只让我的宠物多喝热水吗?

结果显然是不行的,所以我需要去找宠物医生这些更专业的人来帮我的宠物治病。

这个时候,代理就出现了,而宠物医生就是代理,而我就是目标对象。

总结起来就是代理代替目标对象执行相关操作,即是对目标对象的一种功能扩展。

使用代理模式的条件

1、两个角色:执行者,被代理对象

2、注重过程,必须要做,被代理的对象没时间做或者不想做,不专业

3、执行者必须拿到被代理对象的个人资料

1.静态代理

代码实现:

/**
* 我和宠物医生都是人,都有治疗技能,但是宠物医生比我更专业
*/
interface IPerson{
void treat(Pet pet); //治疗技能
}
/**
* 宠物类
*/
class Pet{
private String name;
public Pet(String name){
this.name = name;
}
public String getName() {
return name;
}
} /**
* 目标对象实现”IPerson“接口
*/
class Self implements IPerson{
private Pet pet;
public Self(Pet pet){
this.pet = pet;
}
public void treat(Pet pet){
System.out.println(pet.getName() + ",你要多喝点水");
}
} /**
* 代理对象与目标对象实现同一接口
*/
class PetDoctor implements IPerson{
//接收目标对象
private IPerson targetObj;
public PetDoctor(IPerson targetObj){
this.targetObj = targetObj;
}
@Override
public void treat(Pet pet) {
System.out.println("对" + pet.getName() + "进行检查");
targetObj.treat(pet);
System.out.println("对" + pet.getName() + "进行治疗");
}
}

代码测试:

public static void main(String[] args){
//我的宠物
Pet pet = new Pet("多多");
//目标对象
IPerson target = new Self(pet);
//代理对象
IPerson proxy = new PetDoctor(target);
proxy.treat(pet);
}

运行结果:

宠物医生对多多进行检查
我对多多说,你要多喝点水
宠物医生对多多进行治疗

结果很明显,医生比我更专业,我只会让我的宠物喝水,但医生会先检查再进行专业的治疗,所以说代理是让更专业的对象帮你做事。

2.动态代理

动态代理又分为jdk动态代理和cglib动态代理,两者的区别是jdk动态代理的实现是基于接口,而cglib动态代理是基于继承,但两者做的是同一件事,那就是字节码重组

基本流程都是根据目标对象的资料,通过反射获取该对象的信息,然后根据信息按照特定的写法重写一个java类,再进行编译并动态加载到JVM中运行,所以说动态代理在底层其实就是实现了字节码重组。

jdk动态代理实例演示

Person接口

//定义Person接口,技能是煮饭
public interface Person {
void cook();
}

我自己,也就是被代理的对象,但我只会做可乐鸡翅

public class Oneself implements Person {
@Override
public void cook() {
System.out.println("我会做可乐鸡翅");
}
}

动态代理类,也是一个厨师,因为初始对于做菜比我更专业

public class Kitchener implements InvocationHandler{
//需要代理的目标对象
private Object object; public Kitchener(Object object){
this.object = object;
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我会做糖醋排骨");
method.invoke(object,args); //这是我会做的,其余两样是代理对象初始会做的
System.out.println("我会做九转大肠");
return null;
}
}

测试代码

public class TestJdk {
public static void main(String[] args){
//创建目标代理对象
Oneself oneself = new Oneself(); InvocationHandler kitchener = new Kitchener(oneself);
/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,做的就是字节码重组的工作,新生成一个java类在编译再加载到JVM运行
* 第一个参数是类加载器
* 第二个参数是我们这里为代理对象提供的接口,也就是代理对象所实现的接口,所以说在jdk动态代理中被代理对象需要实现一个接口
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Person proxy = (Person) Proxy.newProxyInstance(kitchener.getClass().getClassLoader(),
oneself.getClass().getInterfaces(),
kitchener);
System.out.println(proxy.getClass()); // (1)
proxy.cook(); }
}

测试结果

class com.sun.proxy.$Proxy0    //(2)
我会做糖醋排骨
我会做可乐鸡翅
我会做九转大肠

可以看到(1)行代码打印出来的是一个代理类,而代理对象通过生成java类再编译加载运行对用户来说是无感知的,我们只知道返回回来的是一个代理对象,然后由代理对象去帮我们做事。

而cglib代理的实现原理也是一样的,只不过一个是基于接口,一个是基于继承,原理都是通过反射获取对象信息再根据对象信息创建java类编译加载运行,所以cglib暂时就不展开了,后期可以自己手写一个动态加深理解。

学习了动态代理后,在本人的工作中是没使用过的,但却是了解spring的AOP实现的必要基础,因为spring的AOP实现就是基于动态代理实现的。

深入理解JAVA中的代理模式的更多相关文章

  1. (转)轻松学,Java 中的代理模式及动态代理

    背景:讲到反射机制,肯定会想到动态代理. 轻松学,Java 中的代理模式及动态代理 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强.值得注意的是,代理类和被代理类应该 ...

  2. 说说Java中的代理模式

    今天看到传智播客李勇老师的JDBC系列的第36节——通过代理模式来保持用户关闭连接的习惯.讲的我彻底蒙蔽了,由于第一次接触代理模式,感到理解很难,在博客园找到一篇文章,先记录如下: 引用自java设计 ...

  3. 谈谈Java中的代理模式

    首先来看一下代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用, 其特征是代理类与 ...

  4. Java中的代理模式--静态代理和动态代理本质理解

    代理模式定义:为其他对象提供了一种代理以控制对这个对象的访问. 代理模式的三种角色: Subject抽象主题角色:抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求. Real ...

  5. Java中的代理模式

    代理模式在Java Web的框架中经常使用到.比如说在对数据库的访问中,核心功能是对数据库的增删改查,而连接数据库.处理事务等功能我们在开发中也要考虑到.所以我们将数据库的CRUD抽象到接口中,然后实 ...

  6. 实例_ Java中的代理模式

    静态代理 我们定义一个接口,并且使用代理模式,想要做到的就是在调用这个接口的实现类时在此方法上添加功能. public interface HelloInterface { void sayHello ...

  7. Java 中的代理模式及动态代理

    原文:https://blog.csdn.net/briblue/article/details/73928350

  8. Objective-C中的委托(代理)模式

    我个人更喜欢把委托(Delegate)模式称为代理(Proxy)模式.还是那句话,第一次接触代理模式是在Java中接触的,在Java中实现代理模式和接口是少不了的.当时学习Spring的时候用到了接口 ...

  9. Java设计模式:代理模式(转)

    代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能.这里使用到编程中的一 ...

随机推荐

  1. sql Server 创建临时表 嵌套循环 添加数据

    begin --通过销货单与明细,生成安装项目及明细,及判断明细是否拆分生成多条 --delete from sazxm --delete from ssbazrw --获取未生成项目的销货单号 ,) ...

  2. c/c++ 继承与多态 文本查询的小例子(智能指针版本)

    为了更好的理解继承和多态,做一个文本查询的小例子. 接口类:Query有2个方法. eval:查询,返回查询结果类QueryResult rep:得到要查询的文本 客户端程序的使用方法: //查询包含 ...

  3. wireshark抓包,安装及简单使用

    跟着实验室师兄尝试做流量分析,趁着离期末考试还有几天,尽快把环境搭好. 采集:自动化测试monkeyrunner,ok 抓包 charles/Wireshark,ok 限制其他应用运行App Moun ...

  4. Linux Mint有进程管理器吗?答案是肯定的

    Linux Mint系统内置了一个系统管理器,叫 "System Monitor",通过 Menu -->> 系统工具 可以查看 . 如下图,在管理器上右键,可以&qu ...

  5. Scrapy框架-Spider

    目录 1. Spider 2.Scrapy源代码 2.1. Scrapy主要属性和方法 3.parse()方法的工作机制 1. Spider Spider类定义了如何爬取某个(或某些)网站.包括了爬取 ...

  6. c++11の关联容器

    一.关联容器 C++的容器类型可以分为顺序容器和关联容器两大类.对于关联容器,主要有map和set,对于这两种,根据不同的维度,衍生出了8种容器 map                        ...

  7. 随机数据生成与对拍【c++版,良心讲解】

    10.7更新:见最下面 离NOIP2018没剩多长时间了,我突然发现我连对拍还不会,于是赶紧到网上找资料,找了半天发现了一个特别妙的程序,用c++写的! 不过先讲讲随机数据生成吧. 很简单,就是写一个 ...

  8. 三。Hibernate 注解形式

    Hibernate支持JPA注解的jar包 JPA全称: Java Persistence API JPA和Hibernate之间的关系,可以简单的理解为JPA是标准接口,Hibernate是实现. ...

  9. VC++6.0

    for 循环的小括号中 不可以定义变量 我也是醉了

  10. ASP.NET Core 2.2 十九. Action参数的映射与模型绑定

    前文说道了Action的激活,这里有个关键的操作就是Action参数的映射与模型绑定,这里即涉及到简单的string.int等类型,也包含Json等复杂类型,本文详细分享一下这一过程.(ASP.NET ...