已阅读5页,还剩7页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
java 反射实现动态代理工厂反射实现动态代理工厂 Proxy 场景场景 有个类 大排档 Stall 它有个方法 提供饭菜 providedMeals 就是 来吃饭 有个类 饭馆 Restaurant 它有个方法 提供饭菜 providedMeals 这两个类有个特点 都是提供吃饭的地方 都有相同的方法 提供饭菜 providedMeals 那可以定义一个接口 提供吃的地方 ProvidedEatOfLocal 它有个抽象方法 提供 饭菜 providedMeals 用这两个类去实现这个接口 不管是 大排档 还是 饭馆 在 提供饭菜 providedMeals 前要做 点餐 ordering 的工作 之后要做 埋单 payMoney 的工作 那我们在实现 大排档 和 饭馆 的 提供饭菜 providedMeals 方法时 把这 点餐 ordering 和 埋单 payMoney 的代码加在一前一后就可以啦 问题问题 但这是重复代码 如果 点餐 的流程发生了改变 比如从人工点餐变成了机器点餐 那 每个实现类的方法实现里面都需要改源代码 现在只有两个实现类 如果现在又新出现个 大酒店 GrandHotel 类 它也有个方法 提供饭菜 providedMeals 它也实现接口 提供吃的地方 ProvidedEatOfLocal 以后有更多的类都来实现这个接口 实现类越多 那 提供饭菜 providedMeals 方法的 前后工作一发生改变 那修改的类就会越多 这在设计上是不合理的 解决方案解决方案 我们可以考虑代理模式 我们创建一个代理人 吃货经纪人 FoodGoodsBroker 吃货经纪人 可以代理所有 提供吃的地方 的实现类 我们只要有和 吃货经纪人 打交道 从他这里我们可以得到我们吃饭的地方去吃饭 吃饭前后的统一动作 点餐 埋单 这个 吃货经纪人 会处理 实际用餐的人可以不关心啦 难道这就是传说中的 吃霸王餐 不给钱 所有实现了 提供吃的地方 的实现类都和 吃货经纪人 打交道 把吃饭前后的统一动 作 点餐 埋单 交给 吃货经纪人 会处理 点餐 和 埋单 的行为如果有变 化就统一变化 如果新来个 提供吃的地方 的实现类也想这么处理 那它也和 吃货经 纪人 打交道 如上所述 实际使用者 用餐的人 是不去关心各种饭店的具体各种的 而新来的饭店如 果可要照这么做 也只要和 吃货经纪人 打交道 就能做到统一处理 而这些统一处理 的地方如果方法改变 那就都改变 不要去修改每个实现类的具体方法 这样最累的就是 吃货经纪人 而提供者 实现了 提供吃的地方 的实现类 和使用者 是完全脱离的 完全符合软件设计的开闭原则 是不是很一横一撇一捺 外带四把 X 另外一个场景也能说明这个问题 数据库的操作有增 删 改 查 在做这四个操作前都要开打一个数据库连接 做完操作后都要关闭这个连接 如果开连接和关连接的代码发生改变 那很多的地方都要改变 这时可以用代理 统一处理这些工作 1 ProvidedEatOfLocal java package com luo rtti proxy3 定义接口 提供吃饭的地方 public interface ProvidedEatOfLocal 抽象方法 提供饭菜 void providedMeals 2 Stall java package com luo rtti proxy3 定义实现类 大排档 实现 提供吃饭的地方 public class Stall implements ProvidedEatOfLocal 地方的名字 String local name 胖哥大排档 实现方法 提供饭菜 public void providedMeals System out println 马路边 塑料凳 烧烤 砂锅粥 诸葛烤鱼 还 有很多吃的 小龙虾 3 Restaurant java package com luo rtti proxy3 定义实现类 饭馆 实现 提供吃饭的地方 public class Restaurant implements ProvidedEatOfLocal 地方的名字 String local name 湘粤情饭馆 实现方法 提供饭菜 public void providedMeals System out println 空调下 坐雅座 红烧肉 清蒸鱼 茄角之恋 还有很多吃的 排骨汤 4 config properties Stall com luo rtti proxy3 Stall Restaurant com luo rtti proxy3 Restaurant 5 FoodGoodsBroker java package com luo rtti proxy3 import java io FileInputStream import java lang reflect Field import java lang reflect InvocationHandler import java lang reflect Method import java lang reflect Proxy import java lang reflect Type import java util Enumeration import java util Properties public class FoodGoodsBroker implements InvocationHandler 实际代理目标 private Object target null 从配置文件中读取 n 个实现了 吃饭的地方 接口的现实类 分别实例化对象后存储在数组中 private static ProvidedEatOfLocal pels null 从配置文件中读取 n 个实现了 吃饭的地方 接口的现实类的类名 把所有类名存储在数组中 private static String restaurantNames 配置文件地址 private static final String CONFIG NAME src com luo rtti proxy3 config properties 接口名 private static final String INTERFACE NAME com luo rtti proxy3 ProvidedEatOfLocal 分隔文件名的标志 根据反射得到某个类实现的接口名称实际为 interface 包名 接口名 我们只需要后 面的 包名 接口名 不需要的 interface 内容 private static final String SEPARATED NAME MARK 用静态块来读取配置文件 实例化配置的实现类的对象 放置于数组中 static System out println 吃货经纪人 开始加载 用 Properties 读取配置文件中的配置的实际被代理的类 Properties readConfig new Properties try 读取配置文件 FoodGoodsBroker readConfig readConfig 统计被代理的类都是实现了 吃饭的地方 的具体数量 实例化数组时设置长度用 int implementCount 0 implementCount FoodGoodsBroker countSestaurants readConfig System out println 配置了 implementCount 个 FoodGoodsBroker INTERFACE NAME 接口的实现类 实例化这些实现类的对象 放置于数组中 FoodGoodsBroker createExamples readConfig implementCount System out println 吃货经纪人 加载完毕 n catch Exception e System out println 读取配置文件 实例化对象 时出现异常 e printStackTrace finally 跟根据业务需要编写这部分的代码 用 Properties 读取配置文件中的配置的实际被代理的类 private static void readConfig Properties readConfig throws Exception readConfig load new FileInputStream CONFIG NAME 统计配置的类有多少实现了接口 private static int countSestaurants Properties readConfig throws Exception 获取配置文件中所有的 key Enumeration keys readConfig propertyNames 统计 配置实现规定接口的实现类的数量 int implementCount 0 遍历配置文件文件所有的 key 类名 while keys hasMoreElements 得到配置文件的某一项 key 类名 和 value 包 类名 String key String keys nextElement String valueClass readConfig getProperty key 得到配置的实现类的类对象 Class c Class forName valueClass 得到类对象实现的所有接口 Type is c getGenericInterfaces 遍历这些所有的接口名 for Type t is 截取正确的接口名 String interName t toString interName interName substring interName indexOf SEPARATED NAME MARK 1 如果有某个实现的接口名和规定的接口名一样 则统计数量 1 if INTERFACE NAME equals interName implementCount break return implementCount 实例化这些实现类的对象 放置于数组中 private static void createExamples Properties readConfig int implementCount throws Exception 如果统计出来 配置实现规定接口的实现类的数量 数量 1 就不要做下面的 工作啦 if implementCount 1 return 给实现 规定接口的现实类 的对象数组初始化长度 给实现 规定接口的现实类 的类名数组初始化长度 pels new ProvidedEatOfLocal implementCount restaurantNames new String implementCount 获取配置文件中所有的 key Enumeration keys readConfig propertyNames 给数组填充值时的下标 从 0 开始 int index 0 遍历配置文件文件所有的 key 类名 while keys hasMoreElements 得到配置文件的某一项 key 类名 和 value 包 类名 String key String keys nextElement String valueClass readConfig getProperty key 得到配置的实现类的类对象 Class c Class forName valueClass 得到类对象实现的所有接口 Type is c getGenericInterfaces 遍历这些所有的接口名 for Type t is 截取正确的接口名 String interName t toString interName interName substring interName indexOf SEPARATED NAME MARK 1 如果有某个实现的接口名和规定的接口名一样 if INTERFACE NAME equals interName 把配置的类名放置正确下标的数组中 restaurantNames index key 通过实现类的类对象得到实现类的实例 把示例放置正确下标的数组中 Object o c newInstance pels index ProvidedEatOfLocal o 下标 1 index 私有化构造方法 创建代理类 类对象中有被代理的接口实现类的对象引用 private FoodGoodsBroker ProvidedEatOfLocal target this target target 饭前 根据业务需要给设置为静态方法 private void eatFront String name 暂时不知道名称的地方 try Field f this getTarget getClass getDeclaredField local name name f get this target toString catch Exception e System out println 读取吃饭的地方名称出现异常 e printStackTrace finally System out println 来到 name 吃东西 System out println 吃饭前干什么呢 开始点餐 饭后 根据业务需要给设置为静态方法 private void eatAfter System out println 吃饭后干什么呢 埋单 擦嘴 抬屁股走人 n 通过代理形式得到的实现类对象 调用方法后实现实行的方法体 实现 InvocationHandler 接口的实现方法 在代理实例上处理方法调用并返回结果 public Object invoke Object proxy Method method Object args throws Throwable this eatFront Object result method invoke target args this eatAfter return result 实际产生代理 外部通过此方法的调用得到被代理的接口实现类的对象 public static ProvidedEatOfLocal getProvidedEatOfLocal String restaurantName 得到数组长度 int length FoodGoodsBroker restaurantNames length 遍历 存储了实现正确接口的类名数组 for int i 0 i length i 如果外部要得到的实例类名和数组中的某个相同 if FoodGoodsBroker restaurantNames i equals restaurantName 把实现类的实例从数组中得到 放置时的下标就是对应的 ProvidedEatOfLocal pel pels i 创建代理类 类对象中有被代理的接口实现类的对象引用 FoodGoodsBroker fb new FoodGoodsBroker pel 得到一个被代理的类对象实例 而且这个被代理的类对象和代理类对象 有联系啦 通过这个方法被代理类 从数组中拿出来的 pel 和代理类对象 含 被代理类对象的 fb 已经产生了联系 Object o Proxy newProxyInstance pel getClass getClassLoader pel getClass getInterfaces fb 得到的被代理的类对象实例其实就是它本身实现的接口类型 return ProvidedEatOfLocal o return null 得到存储了实现正确接口的类名数组 public static String getRestaurantNames return restaurantNames private Object getTarget return target 6 Test java package com luo rtti proxy3 public class Test public static void main String args throws Exception 加载代理类的类定义 只要用了代理类就会自动加载 本句代码在此场景中无实质意义 可以不写 Class forName com luo rtti proxy3 FoodGoodsBroker ProvidedEatOfLocal pel null 拿到所有现实类的类名 String names FoodGoodsBroker getRestaurantNames 变量所有类名 for String name names 根据某个类名得到已经产生代理联系的实现类的对象实例 pel FoodGoodsBroker getProvidedEatOfLocal name 调用对象实例的方法 因为和代理类对象已经有了关系 所有会通知到代理类对象 代理类对象会 做点自己想做的事情 pel providedMeals 暂只配置了com luo rtti proxy3 Stall和com luo rtti proxy3 Restaurant 运行结果运行结果 吃货经纪人 开始加载 配置了 2 个 com luo rtti proxy3 ProvidedEatOfLocal 接口的实现类 吃货经纪人 加载完毕 来到 胖哥大排档 吃东西 吃饭前干什么呢 开始点餐 马路边 塑料凳 烧烤 砂锅粥 诸葛烤鱼 还有很多吃的 小龙虾 吃饭后干什么呢 埋单 擦嘴 抬屁股走人 来到 湘粤情
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年医务人员医德考评结果运用管理办法
- 2026年基于大数据的学生体育素养评价体系重构
- 上海立达学院《安全法规》2025-2026学年第一学期期末试卷(A卷)
- 2026年加油站车辆冲撞防范措施
- 2026年公立医院药品集中采购操作规范与实施细则
- 上海立信会计金融学院《安装工程技术》2025-2026学年第一学期期末试卷(B卷)
- 缩量交易策略组合研究
- 2026年医疗卫生机构耗材采购与使用审计
- 2026年防暴叉生产用模具设计与制造
- 2026年儿童专用药市场缺口与未来发展方向预测
- 2026第18个防灾减灾日提高防灾减灾救灾能力宣传
- 第一二章 野生植物资源开发(总论)
- 2016SSZN-MJG 装配式建筑系列标准应用实施指南(木结构建筑)
- 《2和5的倍数的特征》课件(省一等奖)
- 马鞍山三基轻合金成型科技有限公司年产30000吨轻量化高性能铝合金零部件项目环境影响报告表
- 购物广场夏季空调开关管理规定
- JJG 693-2011可燃气体检测报警器
- GB/T 18707.1-2002机械振动评价车辆座椅振动的实验室方法第1部分:基本要求
- GB/T 17044-2020钢丝绳芯输送带覆盖层与带芯层粘合强度试验
- 清远市城市树木修剪技术指引(试行)
- 北京福赛尔V6891、V6851控制器(联动型)的调试
评论
0/150
提交评论