个人网站是商业的吗,山东网站优化,印度软件外包,广州网络推广机构1.代理模式概述
学习内容
1#xff09;概述
为什么要有 “代理” #xff1f;
生活中就有很多例子#xff0c;比如委托业务#xff0c;黄牛#xff08;票贩子#xff09;等等代理就是被代理者没有能力或者不愿意去完成某件事情#xff0c;需要找个人代替自己去完成这…1.代理模式概述
学习内容
1概述
为什么要有 “代理”
生活中就有很多例子比如委托业务黄牛票贩子等等代理就是被代理者没有能力或者不愿意去完成某件事情需要找个人代替自己去完成这件事这才是“代理”存在的原因。例如要租房子房产中介可以在我们住房前代理我们找房子。中介就是代理而自己就是被代理了。
在代码设计中代理模式作用主要就是让 “被代理对象” 的某个方法执行之前或者执行之后加入其他增强逻辑。
前增强 : 例如获取当前时间被代理对象调用方法后增强 : 例如获取当前时间计算方法执行的时间2代理的前提条件 : 掌握 !
抽象角色 声明功能代理角色 实现抽象功能 , 完成代理逻辑被代理角色 实现抽象功能
意味着被代理角色和代理角色有着共同的父类型既抽象角色 , 例如我要租房子, 我只能找房产中介, 不能找票贩子 代理模式存在两种实现方式 静态代理动态代理
知识小结 请说出代码中代理模式的作用 代理角色对 被代理就角色某个方法执行的前或者后进行 功能增强请说出代理模式中的三个角色 抽象角色
代理角色
被代理角色1.1 静态代理
学习目标
能够写出静态代理模式代码
内容讲解 静态代理是由程序员创建 或 工具生成代理类的源码再编译代理类。 在程序运行前就已经存在代理类的字节码文件代理类和被代理类的关系在运行前就确定了。 简单理解 : 在程序运行之前 , 代理类就存在了,这就是静态代理 ; 动态代理是程序运行时动态生成代理类 静态代理实现的步骤 : 存在一个抽象角色定义被代理角色定义代理增强被代理角色的功能
案例实践
以现实中经纪人代理明星
已知存在接口
// 1.抽象角色
interface Star {// 真人秀方法double liveShow(double money);void sleep();
}定义被代理类
定义王宝强类实现Star方法
// - 定义被代理角色(宝强)
class BaoQiang implements Star {Overridepublic double liveShow(double money) {System.out.println(宝强参加了一个真人秀活动赚了 money 钱);return money;}Overridepublic void sleep() {System.out.println(宝强累了 , 睡觉...);}
}定义代理类
定义宋喆经纪人类
// - 定义代理角色(宋喆)增强被代理角色的功能
class SongZhe implements Star {private BaoQiang baoQiang;public SongZhe(BaoQiang baoQiang) {this.baoQiang baoQiang;}Overridepublic double liveShow(double money) {// 前增强System.out.println(宋喆帮宝强拉了一个真人秀的活动,获取佣金 money * 0.8 元);// 被代理角色的功能double result baoQiang.liveShow(money * 0.2);// 后增强System.out.println(宋喆帮宝强把赚的钱存了起来...);return result;}Overridepublic void sleep() {// 前增强System.out.println(宋喆帮宝强定了一家五星级大酒店);baoQiang.sleep();// 后增强System.out.println(宋喆帮宝强退房...);}
}
定义测试类进行测试
/*静态代理实现的步骤 :- 存在一个抽象角色- 定义被代理角色(宝强)- 定义代理角色(宋喆)增强被代理角色的功能*/
public class StaticAgentDemo {public static void main(String[] args) {// 创建被代理角色 , 没有任何增强BaoQiang baoQiang new BaoQiang();double result baoQiang.liveShow(1000);System.out.println(result);baoQiang.sleep();System.out.println();// 创建代码角色对象 , 可以对被代理角色功能做前后增强SongZhe songZhe new SongZhe(baoQiang);double result2 songZhe.liveShow(1000);System.out.println(result2);songZhe.sleep();}
}关系图 宋喆和宝强都有共同的父类型。他们的业务方法都是一样。
静态代理和装饰模式的对比 :
BufferedRead(FileRead)
1 装饰设计模式是功能扩展功能,在原有的功能基础之上增加了新的功能
2 而代理主要对功能的前后做了增强
知识小结 请问什么叫做静态代理 代码执行前已经确定了代理的代码逻辑。
2. 动态代理
学习目标
能够知道什么是动态代理能够熟悉动态代理相关API能够熟悉动态代理代码执行流程
内容讲解
1概述
在实际开发过程中往往我们自己不会去创建代理类而是通过JDK提供的Proxy类在程序运行时运用反射机制动态创建而成
这就是我们所谓的动态代理。
与静态代理之间的区别在于不用自己写代理类虽然我们不需要自己定义代理类创建代理对象
但是我们要定义对被代理对象直接访问方法的拦截原因就是对拦截的方法做增强。
动态代理技术在框架中使用居多例如很快要学到的数据库框架MyBatis框架等一些主流框架技术SpringSpringMVC中都使用了动态代理技术。
2API学习
Proxy类
java.lang.reflect.Proxy类提供了用于创建动态代理类和对象的静态方法
它还是由这些方法创建的所有动态代理类的超类代理类的父类是Proxy。
public static Object newProxyInstance (ClassLoader loader, Class?[] interfaces, InvocationHandler h ) 获取代理对象的方法 - 返回值该方法返回就是动态生成的代理对象
- 参数列表说明1. ClassLoader loader - 定义代理类的类加载器2. Class?[] interfaces - 代理类要实现的接口列表要求与被代理类的接口一样。3. InvocationHandler h - 就是具体实现代理逻辑的接口InvocationHandler接口
源码
interface InvocationHandler{public Object invoke(Object proxy, Method method, Object[] args); //代理逻辑
}java.lang.reflect.InvocationHandler是代理对象的实际处理代理逻辑的接口具体代理实现逻辑在其 invoke 方法中。所有代理对象调用的方法执行是都会经过invoke。因此如果要对某个方法进行代理增强就可以在这个invoke方法中进行定义。
方法说明如下
public Object invoke(Object proxy, Method method, Object[] args);1. 返回值方法被代理后执行的结果。
2. 参数列表1. proxy - 就是代理对象2. method - 代理对象调用的方法3. args - 代理对象调用方法传入参数值的对象数组.3代码实践
将经纪人代理明星的案例使用动态代理实现
把父接口定义定义被代理类宝强动态生成代理类定义代理逻辑
package com.itheima.dynamicproxy_demo;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 测试类
/*1 Proxy类 :public static Object newProxyInstance (ClassLoader loader,Class?[] interfaces,InvocationHandler h ) 获取代理对象的方法- 返回值该方法返回就是动态生成的代理对象- 参数列表说明1. ClassLoader loader - 定义代理类的类加载器2. Class?[] interfaces - 代理类要实现的接口列表要求与被代理类的接口一样。3. InvocationHandler h - 就是具体实现代理逻辑的接口2 InvocationHandler接口public Object invoke(Object proxy, Method method, Object[] args);1. 返回值方法被代理后执行的结果。2. 参数列表1. proxy - 就是代理对象2. method - 代理对象调用的方法3. args - 代理对象调用方法传入参数值的对象数组.*/
public class DynamicProxyDemo {public static void main(String[] args) {// Proxy.newProxyInstance(被代理角色的类加载器 , 被代理角色实现的所有接口 , 处理器);// 被代理角色的类加载器ClassLoader classLoader BaoQiang.class.getClassLoader();// 被代理角色实现的所有接口Class?[] interfaces BaoQiang.class.getInterfaces();// 创建被代理角色对象BaoQiang baoQiang new BaoQiang();// 代理角色 , 动态生成Star songZhe (Star) Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler(baoQiang));// 代理角色调用liveShow方法songZhe.liveShow(1000);songZhe.sleep();}
}// 定义InvocationHandler接口的实现类
class MyInvocationHandler implements InvocationHandler {private BaoQiang baoQiang;public MyInvocationHandler(BaoQiang baoQiang) {this.baoQiang baoQiang;}// invoke什么时候会执行????// 代理对象调用功能 , 就会触发invoke方法// 此方法对被代理角色的功能做增强// method : 代理对象调用功能就会触发invoke方法 , invoke方法中的method代表的就是调用的方法对象Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals(liveShow)) {// 代理角色对象调用liveShow方法 , 此位置会拦截// 前增强System.out.println(宋喆帮宝强拉了一个真人秀的活动,获取佣金 (double) args[0] * 0.8 元);Object result method.invoke(baoQiang, (double) args[0] * 0.2);// 后增强System.out.println(宋喆帮宝强把赚的钱存了起来...);return result;} else if (method.getName().equals(sleep)) {// 代理角色对象调用sleep方法 , 此位置会拦截method.invoke(baoQiang);} else {// 除了liveShow和sleep方法 , 会执行else代码块中的内容}return null;}
}// 1 抽象角色
interface Star {double liveShow(double money);void sleep();
}// 2 定义被代理角色(宝强)
class BaoQiang implements Star {Overridepublic double liveShow(double money) {System.out.println(宝强参加了一个真人秀活动赚了 money 钱);return money;}Overridepublic void sleep() {System.out.println(宝强累了 , 睡觉...);}
}
动态代理调用流程 小结 什么是动态代理 在代码执行前没有代理类代理类是在程序运行的时候动态生成. Proxy.newProxyInstance动态代理有什么好处 动态代理可以为 “被代理对象” 的所有接口的所有方法做代理动态代理可以在不改变方法源码的情况下实现对方法功能的增强。 动态代理相关的API有哪些 Proxypublic static Object newProxyInstance(类加载器接口列表调用处理器)类加载器 被代理对象.getClass().getClassLoader();接口列表 被代理对象.getClass().getInterfaces();调用处理器 new InvocationHandler(){ 实现 invoke 方法 };InvocationHandlerpublic Object invoke(代理对象,方法对象,方法的实参类别) 该方法执行时机是代理对象调用方法时触发执行动态代理类的字节码在程序运行时由Java反射机制动态生成无需程序员手工编写它的源代码。 缺点 只能针对接口的实现类做代理对象普通类是不能做代理对象的。 后面框架学习的时候会接触到CGLibCode Genneration Library 可以实现对类的代理