文章目录

  • 代理模式的定义
  • 代理模式的作用
  • 代理模式三要素
  • 静态代理
  • 动态代理
    • Spring动态代理的两种实现方式
    • 为什么使用CGLIB动态代理
    • 什么是 CGLIB
    • JDK动态代理和CGLIB字节码生成的区别
    • JDK动态代理的实现
    • CGLIB动态代理的实现
  • AOP和动态代理的关系
  • 动态代理失效的情况分析

代理模式的定义

给目标对象提供一个代理对象,并由代理对象控制目标对象的引用

代理模式的作用

  • 通过代理对象对目标对象进行业务增强
  • 间接访问目标对象,防止直接访问目标对象带来的复杂性【这个作用目前没有理解】

代理模式三要素

  • 抽象接口,定义功能行为
  • 真实对象,实现了抽象对象
  • 代理对象,实现了抽象对象,并包含了真实对象
    静态代理和动态代理,代理对象都必须持有目标对象【被代理对象,也称为目标对象】

    静态代理时,被代理对象和代理对象都必须实现接口,且必须是同一个接口。
    动态代理时,被代理对象必须实现接口,因为代理对象是通过该接口的反射机制创建的,即
    代理对象=Proxy.newProxyInstance(被代理对象.getClass().getClassLoader(),被代理对象.getClass().getInterfaces(), this);

静态代理

Demo实现的功能:代理苹果手机专卖店,在网上买手机,增强了打广告的功能

//抽象对象
public interface PhoneShop {void sellPhone(String phoneName);
}
//被代理的目标对象
public class ApplePhoneShop implements PhoneShop {@Overridepublic void sellPhone(String phoneName) {System.out.println("苹果手机专门店正在卖:" + phoneName);}
}
//用于增强的代理对象
public class OnlineShop implements PhoneShop {private PhoneShop phoneShop;public OnlineShop(PhoneShop phoneShop) {this.phoneShop= phoneShop;}@Overridepublic void sellPhone(String phoneName) {System.out.println("手机广告推广");phoneShop.sellPhone(phoneName);System.out.println("卖完了分钱");}
}
public class StaticProxyDemo {public static void main(String[] args) {OnlineShop onlineShop = new OnlineShop(new ApplePhoneShop());onlineShop.sellPhone("苹果12 pro");}
}

运行结果:

静态代理的缺点:
静态代理的扩展性不好,如果想在接口中增加方法,必须修改代理对象中的代码,明显违背了开闭原则。为了解决静态代理的缺点,由此出现了动态代理。
开闭原则【对扩展开放,对修改关闭】:只额外增加代码模块,不修改原有功能代码

动态代理

Spring动态代理的两种实现方式

java动态代理:通过java.lang.reflect.Proxy类的newProxyInstance方法创建代理对象【反射机制】,再通过代理对象调用被代理对象的方法,实际是通过invoke方法调用
cglib动态代理【Code Generator Library】:修改内存中目标对象类的字节码文件,生成其子类。

为什么使用CGLIB动态代理

JDK动态代理要求代理对象类必须实现接口,不能代理没有实现接口的普通类,因为JDK动态代理创建代理对象时,是通过接口反射机制来实现的:Proxy.newProxyInstance(被代理对象.getClass().getClassLoader(),被代理对象.getClass().getInterfaces(), this);

什么是 CGLIB

CGLIB(Code Generator Library)是一个代码生成库。其被广泛应用于AOP框架。GLIB底层使用了ASM(一个短小精悍的字节码操作框架)来操作字节码生成新的类。

JDK动态代理和CGLIB字节码生成的区别

(1)JDK动态代理要求代理对象类必须实现接口,不能代理没有实现接口的普通类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆写其中的方法。
CGlib动态代理不要求代理对象类必须实现接口,CGlib使用的是继承机制,代理类继承委托类。CGlib要求委托类不能是final的,否则会创建代理失败,因为final类是不允许继承的

  1. 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
  2. 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
  3. 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

JDK动态代理的实现

JDK动态代理的条件:
(1)被代理的对象必须要实现接口
(2)实现InvocationHandler接口
(3)使用Proxy.newProxyInstance产生代理对象

1.实现动态代理的两个核心:InvocationHandler接口、Proxy类

  • InvocationHandler接口,提供了invoke方法,实现该方法主要作用:
    代理对象调用被代理对象的方法通过invoke方法来实现
  • Proxy类用来创建一个代理对象,主要通过它的静态方法newProxyInstance方法
public interface Girl {void shopping(String goodsName);void movie(String filmName);
}
public class WangMeiNv implements Girl {@Overridepublic void shopping(String goodsName) {System.out.println("今天王美女买了:" + goodsName);}@Overridepublic void movie(String filmName) {System.out.println("今天王美女看了电影:" + filmName);}
}
public class WangMeiNvPoxy implements InvocationHandler {private Girl girl;public WangMeiNvPoxy() {}public WangMeiNvPoxy(Girl girl) {this.girl = girl;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("调用方法之前做一些事情!");Object ret = method.invoke(girl, args);System.out.println("调用方法之后做一些事情!");return ret;}//创建该代理对象public Object getNewInstance(){return Proxy.newProxyInstance(girl.getClass().getClassLoader(), girl.getClass().getInterfaces(), this);}
}

代理对象的使用

@Test
public void test1(){Girl wangMeiNv = new WangMeiNv();WangMeiNvPoxy wangMeiNvPoxy = new WangMeiNvPoxy(wangMeiNv);Girl newInstance = (Girl) wangMeiNvPoxy.getNewInstance();newInstance.shopping("超短裙");System.out.println("--------------------");newInstance.movie("坦坦尼克号");}调用方法之前做一些事情!
今天王美女买了:超短裙
调用方法之后做一些事情!
--------------------------
调用方法之前做一些事情!
今天王美女看了电影:坦坦尼克号
调用方法之后做一些事情!

CGLIB动态代理的实现

参考文章:
https://www.jianshu.com/p/296684ba7fe6
https://blog.csdn.net/gyshun/article/details/81000997

AOP和动态代理的关系

  • AOP面向切面编程是一种编程思想,是一种横向抽取代码的机制,补充了面向对象编程思想只能纵向父子集成的不足。
  • 动态代理只是AOP这种编程思想的实现方式之一
  • Spring的AOP是基于动态代理和反射机制实现的

动态代理失效的情况分析

public interface Girl {void shopping(String goodsName);void movie(String filmName);
}
public class WangMeiNv implements Girl {@Overridepublic void shopping(String goodsName) {System.out.println("==============这里此次代码分析的重点=================");//这里此次代码分析的重点this.movie("泰塔尼克号");}@Overridepublic void movie(String filmName) {System.out.println("今天王美女看了电影:" + filmName);}
}
public class WangMeiNvPoxy implements InvocationHandler {private Girl girl;public WangMeiNvPoxy() {}public WangMeiNvPoxy(Girl girl) {this.girl = girl;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("调用方法之前做一些事情!");Object ret = method.invoke(girl, args);System.out.println("调用方法之后做一些事情!");return ret;}//创建该代理对象,这里this代表实现InvocationHandler接口的当前代理对象public Object getNewInstance(){return Proxy.newProxyInstance(girl.getClass().getClassLoader(), girl.getClass().getInterfaces(), this);}
}
@Test
public void test1(){Girl wangMeiNv = new WangMeiNv();WangMeiNvPoxy wangMeiNvPoxy = new WangMeiNvPoxy(wangMeiNv);Girl newInstance = (Girl) wangMeiNvPoxy.getNewInstance();newInstance.shopping("超短裙");System.out.println("--------------------");//newInstance.movie("坦坦尼克号");}调用方法之前做一些事情!
今天王美女买了:超短裙
==============这里此次代码分析的重点=================
今天王美女看了电影:泰塔尼克号
调用方法之后做一些事情!
--------------------

为什么这次shopping方法中直接调用moive方法后,这里的结果和之前的不同呢?
原因:这里的this指带的WangMeiNv类的对象,而不是代理类实例。只有代理实例调用方法时,方法才会通过AOP实现业务增强处理

public class WangMeiNv implements Girl {@Overridepublic void shopping(String goodsName) {System.out.println("==============这里此次代码分析的重点=================");//这里此次代码分析的重点this.movie("泰塔尼克号");} @Overridepublic void movie(String filmName) {System.out.println("今天王美女看了电影:" + filmName);}
}

解决办法:
https://blog.csdn.net/Dongguabai/article/details/80788585

动态代理模式和动态代理失效原因简介相关推荐

  1. 代理模式、动态代理和面向方面

    代理的意思很好理解,它借鉴了我们日常所用的代理的意思:就是本来该自己亲自去做的某件事,由于某种原因不能直接做,而只能请人代替你做,这个被你请来做事的人就是代理.比如过春节要回家,由于你要上班,没时间去 ...

  2. 【设计模式】--- 装饰器模式、静态代理模式和动态代理模式

    文章目录 1 引子 2 业务场景介绍 3 静态代理模式 4 装饰器模式 5 动态代理模式 5.1 Proxy --- 具体的代理对象生成组件 5.2 InvocationHandler --- 封装被 ...

  3. 设计模式之代理模式(静态代理、Java动态代理、Cglib动态代理)

    代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 提醒:动态代理中涉及到以前的一些知识 ...

  4. 【Java】代理模式(静态代理动态代理)

    CONTENT 代理模式 静态代理 动态代理 JDK 动态代理(基于接口) CGLIB 动态代理(基于类继承) JDK 动态代理 v.s. CGLIB 动态代理 JDK 动态代理为什么必须基于接口 R ...

  5. 设计模式之代理模式(静态代理动态代理)

    目录 1.什么是代理模式 2.代理模式的结构 3.代理模式的实现 3.1 静态代理和动态代理概念 3.2 静态代理 3.3 动态搭理 3.3.1 代码实现 3.3.2 Proxy类讲解 4.动态代理V ...

  6. java动态代理_Java代理模式及动态代理详解

    Java的动态代理在实践中有着广泛的使用场景,比如最场景的Spring AOP.Java注解的获取.日志.用户鉴权等.本篇文章带大家了解一下代理模式.静态代理以及基于JDK原生动态代理. 代理模式 无 ...

  7. 代理模式和动态代理模式_代理模式介绍

    代理模式和动态代理模式 代表:被选中或当选为他人投票或代理的人– Merriam-Webster . 委托模式:在软件工程中,委托模式是面向对象编程中的一种设计模式,其中,一个对象而不是执行其陈述的任 ...

  8. 【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)

    文章目录 什么是代理模式 一. 代理模式简介 二. 静态代理模式 三. 动态代理模式 万能模版 前言:笔记基于狂神设计模式视频.<大话设计模式>观后而写 (最近一直在更新之前的刷题博客,今 ...

  9. Java拾遗:007 - 代理模式与动态代理

    2019独角兽企业重金招聘Python工程师标准>>> 代理模式 在日常开发中我们可以会接手一些老的项目,有时连源码都没有,或者有时候我会需要对业务逻辑做一定增强(功能扩展,如:日志 ...

最新文章

  1. PHP APC(可选PHP缓存)
  2. Python用selenium获取Cookie并用于登录。
  3. MySQL主键学习总结
  4. nginx 学习笔记(6) nginx配置文件中的度量单位
  5. Android学习--持久化(三) SQLite LitePal
  6. python读txt文件 数组-python将txt等文件中的数据读为numpy数组的方法
  7. Qt那些事0.0.2
  8. mysql报错01427_ORA-01427问题的分析和解决
  9. My first project
  10. dubbo服务RpcException异常:Tried 3 times of the providers 或com.alibaba.dubbo.remoting.TimeoutException
  11. 快速突破面试算法之双指针篇
  12. 使用eclipse开发jsp项目入门
  13. python图像质量评价_图像质量评价和视频质量评价(IQA/VQA)
  14. The client is closed
  15. Fluent Mybatis 牛逼!
  16. HBase-14.1-JMX监控实战-hadoop
  17. 华硕电脑装linux黑屏,华硕电脑更新显卡后开机黑屏应该怎么解决
  18. 办公系统服务器搭建,搭建云桌面办公服务器
  19. 【UEFI实战】HII之常用函数
  20. java json解析jar包,解析json常用jar包

热门文章

  1. 林大ACM培训day3心得
  2. 视频无损放大软件Topaz Video Enhance AI for Mac更新啦
  3. 2020年2月18日 林大OJ习题 set
  4. java实现天干地支纪年
  5. 等保三级安全要求简要攻略-安全物理环境
  6. 取消阅读器小手向下箭头
  7. 2022.02.20
  8. HTML+CSS期末大作业——中华传统文化题材学生网页设计成品(6页面) 学生DW网页设计作业成品 web课程设计网页规划与设计 计算机毕设网页设计源码...
  9. 用js制作一个新年倒计时
  10. Quartz学习之Cron表达式详解