在线网站建设平台,洪山区建设局网站,wordpress菜单栏换色,wordpress好吗本篇主要聊一些23中模型中的代理模式#xff1a;
看一下百度百科的解释#xff1a;
代理模式的定义#xff1a;为其他对象提供一种代理以控制对这个对象的访问。在某些情况下#xff0c;一个对象不适合或者不能直接引用另一个对象#xff0c;而代理对象可以在客户端和目…本篇主要聊一些23中模型中的代理模式
看一下百度百科的解释
代理模式的定义为其他对象提供一种代理以控制对这个对象的访问。在某些情况下一个对象不适合或者不能直接引用另一个对象而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式其实有点像是合作方—经纪人—明星这样关系。
合作方如果想要找明星合作首先要找到经纪人具体的谈判合同的事情先和经纪人进行协商最后达成合作。
其实代理模式有很多不同的形式主要有三种静态代理动态代理JDK代理接口代理Cglib代理。
一般的组成有
抽象角色通过接口或抽象类生命真实角色实现的业务方法。代理角色实现抽象角色是真实角色的代理通过真实角色的业务逻辑方法来实现抽象方法并可以附加自己的操作。真实角色实现抽象角色定义真实角色所要实现的业务逻辑供代理角色调用。
静态代理
静态代理在使用时需要定义接口或者抽象类也就是被代理对象明星与代理对象经纪人需要实现相同的接口或者是继承相同的父类。
现在进行代码演示 接口 public interface BusinessInfa {
// 签约方法void signContract();} 被代理类 public class Star implements BusinessInfa {Overridepublic void signContract() {System.out.println(我是大明星我同意这份合同了);}
} 代理人 public class Agent implements BusinessInfa{
// 代理谁Star star;public Agent(Star star) {this.star star;}Overridepublic void signContract() {
// 先联系明星经纪人System.out.println(你好你找我家明星合作可以和我谈);
// 谈合同不是简单就可以签约的肯定要涉及道各种拉扯合同条款以及费用System.out.println(和经纪人一起疯狂的如果老太太菜市场砍价一般深入几天各种约各种谈);
// 最后同意了合同this.star.signContract();
// 就算合约签了具体后面合作中的事情System.out.println(具体合作后现场一些细节比如我家大明星剧本改下台词超过十个字了记不住台词);}
} 客户端调用代理人 public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有去找大明星公开的经纪人联系System.out.println(我是合作方需要联系大明星没办法只能先联系经纪人);BusinessInfa businessInfanew Agent(new Star());businessInfa.signContract();}}
然后看一下结果 现在看一下静态代理的优缺点
优点 在不修改目标的对象功能的前提下通过代理对象对目标公共进行扩展例子中不会对明星签约的行动进行修改但是具体谈判细节以及合作后的出现事故等投通过经纪人进行谈判毕竟明星给了经纪人钱的。缺点代理对象需要与目标的对象实现一样的接口所以会有很多代理类一旦接口增量了方法目标对象和代理对象都要维护。也就是比如合作定义的行为如果增加了明星和经纪人都需要增加行为。
静态代理其实是最方便理解代理这个原理的而其它无论如何变化都不能离开这个原理。
动态代理jdk代理
动态代理类是位于Java.lang.reflect包下类别的Interface InvocationHandler。其实也是通过反射实现的所以代理对象不需要实现接口但是目标对象要实现接口否则不能用动态代理。而这是利用JDK的API实现的动态代理是在内存中构建代理对象的。
动态代理也被称之为JDK代理接口代理。
还是老规矩直接用代码演示 被代理类接口 //商务接口 毕竟经纪人代理明星的业务也是要统一一下什么业务能代理
public interface BusinessInfa {
// 签约方法void signContract();void breakContract();} 被代理类 public class Agent {// 代理谁Object target;public Agent(Object target) {this.target target;}// 动态创建不同的代理对象public Object getProxyObject(){Object objectProxy.newProxyInstance(this.target.getClass().getClassLoader(),this.target.getClass().getInterfaces(),new myInvocationHandler());return object;}class myInvocationHandler implements InvocationHandler{Override
// proxy 在其上调用方法的代理实例 method被代理的方法 代理方法中的参数argspublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 对第一个参数好奇是什么System.out.println();
// System.out.println(proxy); 这样打印会报错 不过可以看出第一个参数应该是代理对象 一般的时候没有什么用System.out.println(proxy.getClass());System.out.println();// 因为要运行的方法没有返回值所以不接受数据通过return返回了 同时这里也是可以根据反射判断不同的方法然后加入不同的逻辑if(method.getName()signContract || method.getName().equals(signContract)){System.out.println(你好你找我家明星合作可以和我谈);method.invoke(target,args);System.out.println(后期出现事情你们必须改因为我家明星最漂亮哪怕是她的错你们会原谅的。);// 这里可以返回所代理的类要运行的方法不过因为我没有返回值所以直接返回空return null;}else if (method.getName()breakContract || method.getName().equals(breakContract)){System.out.println(你好你们的错误);method.invoke(target,args);System.out.println(可恶的合作方不理你们了);// 这里可以返回所代理的类要运行的方法不过因为我没有返回值所以直接返回空return null;}return null;}}
}调用类 public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有去找大明星公开的经纪人联系System.out.println(我是合作方需要联系大明星没办法只能先联系经纪人);Agent agent new Agent(new Star());BusinessInfa businessInfa (BusinessInfa) agent.getProxyObject();businessInfa.signContract();System.out.println(*********************************************);businessInfa.breakContract();}
}然后看一下输出结果 可以看下类关系图
jdk代理的优缺点
优点 JDK原声动态代理时java原声支持的、不需要任何外部依赖。而且可以动态生成代理类方不需要像静态代理哪里代理类因为接口变化而不停的调整。缺点但是它只能基于接口进行代理也就是被代理的对象也需要有一个接口不然无法使用jdk代理同时因为它已经继承了proxy了java不支持多继承。
动态代理Cglib代理
无论静态代理还是上面提到的JDK动态代理都需要实现一个接口但是有时候对象只是一个单独的对象并没有实现任何的接口这个时候就需要使用目标对象的子类来实现。而聊到的Cglib动态代理就算通过这种方式实现代理的。
Cglib代理也叫做子类代理其是再内存中构建了一个子类对象从而实现对目标对象功能的扩展。Cglib代理是可以再运行期扩展java类与实现java接口所以其广泛被需要AOP框架使用其中就包括spring通过Cglib实现方法拦截。
因为是内存中动态构建子类所以Cglib代理类不能为final。同样如果目标对象的方法如果为final或者static代理也会不对其方法进行代理。
其实AOP中不一定会都选择使用Cglib代理我们开发中同样是如此选择的
目标对象需要实现接口那就使用JDK代理。目标对象不需要实现接口那句使用Cglib代理。
Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。
需要Jar包
这个有两种情况 如果引入的是Cglib的jar包就需要四个包 asm.jar asm-commons.jar asm-tree.jar Cglib-*.*.jar(自己选版本) 如果使用 cglib-nodep的jar直接导入这一个就行因为其打包了cglib所需要的依赖jar包
代码演示 被代理的对象无需实现接口 public class Star {public void signContract() {System.out.println(我是大明星我同意这份合同了);}public void breakContract() {System.out.println(台词超过三句了编辑不修改剧本合作方的错误毁约了。。。。);}
} 使用Cglib代理的增强代理类 // 经纪人代理 需要实现Cglib代理中接口方法MethodInterceptor
public class Agent implements MethodInterceptor {// 代理谁Object target;public Agent(Object target) {this.target target;}// 动态创建不同的代理对象public Object getProxyObject(){
// 创建一个Cglib包下的工具栏Enhancer enhancernew Enhancer();
// 设置父类enhancer.setSuperclass(target.getClass());
// 设置回调函数这个回调本身是自己所以enhancer.setCallback((Callback) this);
// 创建子类对象 也就是代理对象return enhancer.create();}Override
// 需要重写这个方法代理类调用方法的时候会走个方法
// o 代表的this 就算代理增强的对象 Method 被代理对象执行的方法也就是拦截的方法 objects 方法的参数 methodProxy 用于调用super非拦截方法可以根据需要调用多次public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {// 因为要运行的方法没有返回值所以不接受数据通过return返回了 同时这里也是可以根据反射判断不同的方法然后加入不同的逻辑if(method.getName()signContract || method.getName().equals(signContract)){System.out.println(你好你找我家明星合作可以和我谈);method.invoke(target,objects);System.out.println(后期出现事情你们必须改因为我家明星最漂亮哪怕是她的错你们会原谅的。);// 这里可以返回所代理的类要运行的方法不过因为我没有返回值所以直接返回空return null;}else if (method.getName()breakContract || method.getName().equals(breakContract)){System.out.println(你好你们的错误);method.invoke(target,objects);System.out.println(可恶的合作方不理你们了);// 这里可以返回所代理的类要运行的方法不过因为我没有返回值所以直接返回空return null;}return null;}
}调用测试的类 public class client {public static void main(String[] args) {// 需要找大明星的联系方式没有去找大明星公开的经纪人联系System.out.println(我是合作方需要联系大明星没办法只能先联系经纪人);Agent agent new Agent(new Star());Star star (Star) agent.getProxyObject();star.signContract();System.out.println(*********************************************);star.breakContract();}
} 也没有问题可以实现动态代理。
补充 其它代理
这个只是写了几个代理的名字也不是全部。
防火墙代理: 内网通过代理穿透防火墙对公网进行访问。缓存代理 如果获取网络资源有些从缓存中回去资源如果没有了再从其它地方获取资源。远程代理远程代理通过网络和真正的远程对象沟通信息。常见的翻墙梯子就算这个逻辑。同步代理: 主要使用在多线程编程中,完成多线程间同步工作