动态代理模式和动态代理失效原因简介
文章目录
- 代理模式的定义
- 代理模式的作用
- 代理模式三要素
- 静态代理
- 动态代理
- 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类是不允许继承的
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用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 业务场景介绍 3 静态代理模式 4 装饰器模式 5 动态代理模式 5.1 Proxy --- 具体的代理对象生成组件 5.2 InvocationHandler --- 封装被 ...
- 设计模式之代理模式(静态代理、Java动态代理、Cglib动态代理)
代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 提醒:动态代理中涉及到以前的一些知识 ...
- 【Java】代理模式(静态代理动态代理)
CONTENT 代理模式 静态代理 动态代理 JDK 动态代理(基于接口) CGLIB 动态代理(基于类继承) JDK 动态代理 v.s. CGLIB 动态代理 JDK 动态代理为什么必须基于接口 R ...
- 设计模式之代理模式(静态代理动态代理)
目录 1.什么是代理模式 2.代理模式的结构 3.代理模式的实现 3.1 静态代理和动态代理概念 3.2 静态代理 3.3 动态搭理 3.3.1 代码实现 3.3.2 Proxy类讲解 4.动态代理V ...
- java动态代理_Java代理模式及动态代理详解
Java的动态代理在实践中有着广泛的使用场景,比如最场景的Spring AOP.Java注解的获取.日志.用户鉴权等.本篇文章带大家了解一下代理模式.静态代理以及基于JDK原生动态代理. 代理模式 无 ...
- 代理模式和动态代理模式_代理模式介绍
代理模式和动态代理模式 代表:被选中或当选为他人投票或代理的人– Merriam-Webster . 委托模式:在软件工程中,委托模式是面向对象编程中的一种设计模式,其中,一个对象而不是执行其陈述的任 ...
- 【学习笔记】结合代码理解设计模式 —— 代理模式(静态代理、动态代理、延伸)
文章目录 什么是代理模式 一. 代理模式简介 二. 静态代理模式 三. 动态代理模式 万能模版 前言:笔记基于狂神设计模式视频.<大话设计模式>观后而写 (最近一直在更新之前的刷题博客,今 ...
- Java拾遗:007 - 代理模式与动态代理
2019独角兽企业重金招聘Python工程师标准>>> 代理模式 在日常开发中我们可以会接手一些老的项目,有时连源码都没有,或者有时候我会需要对业务逻辑做一定增强(功能扩展,如:日志 ...
最新文章
- PHP APC(可选PHP缓存)
- Python用selenium获取Cookie并用于登录。
- MySQL主键学习总结
- nginx 学习笔记(6) nginx配置文件中的度量单位
- Android学习--持久化(三) SQLite LitePal
- python读txt文件 数组-python将txt等文件中的数据读为numpy数组的方法
- Qt那些事0.0.2
- mysql报错01427_ORA-01427问题的分析和解决
- My first project
- dubbo服务RpcException异常:Tried 3 times of the providers 或com.alibaba.dubbo.remoting.TimeoutException
- 快速突破面试算法之双指针篇
- 使用eclipse开发jsp项目入门
- python图像质量评价_图像质量评价和视频质量评价(IQA/VQA)
- The client is closed
- Fluent Mybatis 牛逼!
- HBase-14.1-JMX监控实战-hadoop
- 华硕电脑装linux黑屏,华硕电脑更新显卡后开机黑屏应该怎么解决
- 办公系统服务器搭建,搭建云桌面办公服务器
- 【UEFI实战】HII之常用函数
- java json解析jar包,解析json常用jar包