当前位置: 首页 > news >正文

专业营销网站公司互联网个人用户网站

专业营销网站公司,互联网个人用户网站,中国有几大建设,网上做室内设计好的网站[程序设计]—代理模式#x1f473; 本文章记录学习于——52.面向切面#xff1a;AOP-场景模拟_哔哩哔哩_bilibili 最近闲来无事#xff0c;在学习Spring的源码#xff1a; 后面慢慢更新源码系列blog#xff0c;希望多多关注#x1f64f;#x1f64f; 目前已经总结的b…[程序设计]—代理模式 本文章记录学习于——52.面向切面AOP-场景模拟_哔哩哔哩_bilibili 最近闲来无事在学习Spring的源码 后面慢慢更新源码系列blog希望多多关注 目前已经总结的blog 系列 慈様や 前端学习导航‍ 、小様—Java后端开发日记 很多框架在设计和实现过程中广泛运用了多种设计模式Spring核心IOC、AOP 工厂模式 BeanFactory 和 ApplicationContext 实现了工厂模式负责创建和管理Bean对象 单例模式 Spring 默认 将所有Bean定义为单例模式即每个容器中只存在一个实例 代理模式 AOP 面向切面编程的核心通过动态代理JDK代理、CGLIB代理 实现了非侵入式编程可以在不修改原有业务代码的情况下增加额外功能 在目标方法调用前后添加增强逻辑如事务管理、日志记录等 适配器默认、观察者默认、策略模式… 设计模式使 Spring框架展现出了高度的模块化、可配置性和可扩展性使得开发者能够高效地构建复杂的应用程序 总而颜值-设计模式很重要 设计模式其实是在软件开发过程中经过经验积累和验证总结一套通用代码设计方案 如果熟悉了设计模式当遇到类似的场景我们可以快速地参考设计模式实现代码 不仅可以加速我们的编码速度也提升了代码的扩展性、重用性、维护性! 个人看法 虽然设计模式听着高大上其实实际开发过程中已经潜移默化的接触了很多了 且有的设计模式已经随着时代、或还并没有完全适合的引用常见新手建议会用为主了解为辅 设计模式属于程序的内功心法、学习是一个长期反复推敲的过程、不断优化升级❗ ❗ ❗ 注意设计模式不属于某个特定的编程语言而是一种编程思想代码模式 设计模式分类 目前设计模式主要有23种大致分为三大类 创建型模式 Creational Patterns 用于创建对象的模式同时隐藏对象创建的逻辑 避免代码中出现大量 new 操作和复杂的创建逻辑目的是解耦对象的创建和使用 常用的有 单例模式、工厂模式、建造者模式不常见的有 原型模式 结构型模式 Structural Patterns 用于处理对象组合的结构关注类与对象的组合目的是通过组合对象或类的方式形成更大的结构 常用的有 适配器模式、桥接模式、组合模式、装饰器模式、代理模式不常见的有 外观模式(门面模式)、享元模式 行为型模式Behavioral Patterns 用于定义对象相互协作以完成单个对象无法单独实现的任务目的是定义类和对象间的通信方式 常用的有 观察者模式、责任链模式、策略模式、模板模式、状态模式、迭代器模式不常见的有 备忘录模式、命令模式、中介者模式、访问者模式、解释器模式 需求介绍 目前有一个计算器类它有add 加、sub 减 的方法新需求 计算前后进行日志记录输出 声明计算器接口 用于规范计算器类的定义 //计算器类接口: public interface Calculator {//计算器加函数int add(int i,int j);//计算器减函数int sub(int i,int j); }计算器接口实现类 声明并实现计算器接口 //计算器接口实现类: public class CalculatorImpl implements Calculator {Overridepublic int add(int i, int j) { return ij; }Overridepublic int sub(int i, int j) { return i-j; } }新需求在加减之前进行日志记录——计算器日志接口实现类 正常情况下大部分开发者会直接在上面实现类上改动但为了不影响其他就创建新的实现类 //计算器日志接口实现类: 不就是日志嘛一行代码CV的事~~ public class CalculatorLogImpl implements Calculator {Overridepublic int add(int i, int j) {System.out.println([日志]mul 方法开始了参数是:i, j);System.out.println([日志]mul 方法结束了结果是:(i j));return i j;}Overridepublic int sub(int i, int j) {System.out.println([日志]mul 方法开始了参数是:i, j);System.out.println([日志]mul 方法结束了结果是:(i - j));return i-j;} }轻轻松松~ 小活 这就结束了吗到此为止了… NO—NO—NO❗ ❗ ❗ 如果这个类在大一点呢或者方法实现更复杂呢 针对日志功能实现类我们发现有如下缺陷对核心业务功能有干扰附加功能分散各个业务功能中 主角登场——代理模式 JDK 代理模式 代理模式是一种结构型设计模式 它为其他对象提供一种代理以控制对这个对象的访问代理对象可以在客户端和目标对象之间起到中介的作用 在不改变目标对象接口的前提下对目标对象的访问进行控制或增强上述代码举例 代理模式的特点 功能增强 代理对象可以在访问实际对象之前或之后添加额外的功能间接访问 客户端通过代理访问实际对象代理对象负责对实际对象的控制代码解耦 客户端不直接与实际对象交互通过代理对象可以透明地扩展实际对象的功能 代理模式的分类 静态代理 在编译时创建代理类代理类与目标类实现相同的接口动态代理 在运行时动态生成代理类适用于无需事先定义代理类的场景 静态代理 静态代理不推荐) 了解即可实际开发中不经常使用 代理类和被代理类在 编译时期 就确定了它们之间的代理关系 代理类需要 实现 与被代理类 相同的接口 并且在代理类中持有被代理类的实例 目标对象 通过调用被代理类的方法来完成实际的操作在方法调用前后添加额外的逻辑 这一点也 不高级 //静态代理类 public class CalculatorStaticProxy implements Calculator {//被代理的目标对象private Calculator target;public CalculatorStaticProxy(Calculator target) { this.target target; }Override//附加功能由代理类中的代理方法来实现public int add(int i, int j) {System.out.println([日志] add 方法开始了参数是 i , j);//通过目标对象来实现核心业务逻辑int addResult target.add(i, j);System.out.println([日志] add 方法结束了结果是 addResult);return addResult;}//省略...其他实现; }//静态代理使用: public class CalculatorStaticProxyMain {public static void main(String[] args) {//创建被代理类对象CalculatorImpl calculator new CalculatorImpl();//被代理类对象 构造创建 对应的 静态代理类,静态代理类中对函数进行调用扩展;CalculatorStaticProxy calStaticProxy new CalculatorStaticProxy(calculator);//因此: 直接使用静态代理类对象即可,获得存在日志的计算机函数方法;calStaticProxy.add(1,1);} }静态代理确实实现了解耦但是由于代码都写死了完全不具备任何的灵活性 如果将来其他地方也需要附加日志那还得再声明更多个静态代理类那就产生了大量重复的代码 如何 将日志功能集中到一个代理类中将来有任何日志需求都通过这一个代理类来实现——动态代理技术 动态代理 涉及知识 【反射】、【类加载ClassLoad】… JDK 官方文档 Java.lang.reflect.Proxy Java 动态代理是一种在运行时 动态地创建代理对象的机制 它允许开发者在不修改原有类代码的基础上 为目标对象创建代理并且能够在代理对象的方法调用前后灵活地添加自定义的逻辑 与静态代理不同 动态代理不需要为每个目标类手动编写代理类在JDK中常用的实现方式是 反射 反射机制 是指程序在运行期间可以访问、检测和修改其本身状态或行为的一种能力 实现原理 实现原理 基于 Java 的java.lang.reflect包InvocationHandler接口 开发者需要实现这个接口并且实现invoke方法在invoke方法中定义代理对象的方法被调用时要执行逻辑 invoke方法有三个参数 proxy代理对象本身、method被调用的方法对象、args方法的参数数组 Proxy类 通过Proxy.newProxyInstance 方法可以 创建生成 代理对象这个方法需要三个参数 目标对象的类加载器目标对象.getClass().getClassLoader(),目标对象的接口数组目标对象.getClass().getInterfaces(),InvocationHandler 接口实例 到此就获得了一个(动态)代理对象 使用动态代理对象具有目标对象一样的方法([参数]); 通过代理对象方法时实际上会调用InvocationHandler实例对象的invoke方法方法中执行了增强逻辑 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;//动态代理类 public class DynamicProxy implements InvocationHandler {//目标代理对象private Object target;public DynamicProxy(Object target) { this.target target; }Override//proxy代理对象本身、method被调用的方法对象、args方法的参数数组public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println([日志] method.getName() 方法开始了参数是 args);// 通过目标对象来实现核心业务逻辑Object addResult method.invoke(target, args);System.out.println([日志] method.getName() 方法结束了结果是 addResult);return addResult;} }import org.proxyD.Calculator; import java.lang.reflect.Proxy; import org.proxyD.CalculatorImpl;/** 动态代理使用: */ public class DynamicProxyMain {public static void main(String[] args) {//定义目标对象、InvocationHandler接口实例CalculatorImpl calculator new CalculatorImpl();DynamicProxy calStaticProxy new DynamicProxy(calculator);//Proxy.newProxyInstance(目标类加载对象,目标接口数组,InvocationHandler接口实例) 动态创建生成代理对象Calculator Calculatorimpl (Calculator) Proxy.newProxyInstance(//calculator 目标对象通过接口getClass 获得类加载对象、接口数组calculator.getClass().getClassLoader(),calculator.getClass().getInterfaces(),//InvocationHandler 接口实例calStaticProxy);//使用: 生成代理类Calculatorimpl.add(1,1);Calculatorimpl.sub(1,1);} }动态代理优势 可以在运行时根据需要动态地创建代理对象而不需要像静态代理那样为每个目标类提前编写代理类 代码复用性强一个InvocationHandler实现类可以用于代理多个实现相同接口的目标对象 易于维护和扩展由于代理逻辑集中在InvocationHandler实现类的invoke方法中 当需要修改代理逻辑时只需要修改这个方法即可而不需要多个代理类进行修改 优化—代理工厂 考虑到代码复用与管理 可以对上述代码进行优化一个 代理工厂将Proxy.newProxyInstance 生成代理类操作进行统一管理 匿名内部类实现 InvocationHandler接口重写了invoke方法 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays;//动态代理工厂 public class ProxyFactory {//目标对象private Object target;public ProxyFactory(Object target) { this.target target; }//动态代理对象函数//通过: 创建 InvocationHandler接口 匿名实现类对象,直接返回 动态代理对象;public Object getProxy(){/** newProxyInstance()创建一个代理实例 其中有三个参数: *//** 1、classLoader加载动态生成的代理类的类加载器 */ClassLoader classLoader target.getClass().getClassLoader();/** 2、interfaces目标对象实现的所有接口的class对象所组成的数组 */Class?[] interfaces target.getClass().getInterfaces();/** 3、通过: 创建 InvocationHandler接口 匿名实现类对象,直接返回 动态代理对象* invocationHandler设置代理对象实现目标对象方法的过程即代理类中如何重写接口中的抽象方法 */InvocationHandler invocationHandler new InvocationHandler() {Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result null;try {System.out.println([动态代理][日志] method.getName()参数 Arrays.toString(args));result method.invoke(target, args);System.out.println([动态代理][日志] method.getName()结果 result);} catch (Exception e) {e.printStackTrace();System.out.println([动态代理][日志] method.getName() 异常);} finally {System.out.println([动态代理][日志] 方法执行完毕);}return result;}};//最后返回代理对象;return Proxy.newProxyInstance(classLoader, interfaces, invocationHandler);} }CGLIB 动态代理 JDK动态代理是基于接口的所以要求代理类一定是有定义接口的 CGLIB 基于 ASM 字节码生成工具它是通过 继承的方式生成目标类的子类来实现代理类 注意 final 方法不可继承 它们之间的性能随着 JDK 版本的不同而不同 JDK6 在运行次数较少的情况下动态代理与 CGLIB 差距不明显次数增加之后 CGLIB 更快 JDK7 情况发生了逆转在运行次数较少1.000,000情况下JDK 动态代理比 CGLIB 快了差不多30% 而当调用次数增加之后(50000000)JDK动态代理比 CGLIB 快了接近1倍Jdk8 表现和 Jdk7 基本一致 CGLIB 的工作原理 继承目标类CGLIB 通过 继承目标类 来创建代理类。在生成的代理类中它会重写目标类的方法 方法拦截CGLIB 利用方法拦截器MethodInterceptor来控制对目标类方法的访问 当代理类的方法被调用时会先进入方法拦截器的intercept方法进行操作 添加 CGLIB 依赖CGLIB 是第三方库所以需要引入对应依赖 dependencygroupIdcglib/groupIdartifactIdcglib-nodep/artifactIdversion3.3.0/version /dependency创建方法拦截器实现 CGLIB 的MethodInterceptor接口来定义方法拦截逻辑重写intercept方法 第一个参数o是代理对象本身 第二个参数method是被调用的目标方法 第三个参数objects是目标方法的参数数组 第四个参数methodProxy是一个方法代理对象用于调用目标类的原始方法 通过methodProxy.invokeSuper(o, objects)可以调用目标类的原始方法并获取返回结果 import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; //实现 CGLIB 的MethodInterceptor接口来定义方法拦截逻辑 public class CglibInterceptor implements MethodInterceptor {Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println(代理类在目标方法执行前的操作method.getName());Object result methodProxy.invokeSuper(o, objects);System.out.println(代理类在目标方法执行后结果result);return result;} }//CGLIB 的Enhancer类来创建代理对象 import net.sf.cglib.proxy.Enhancer; public class CglibInterceptorMain {public static void main(String[] args) {//首先创建一个Enhancer对象Enhancer enhancer new Enhancer();//设置代理类要继承的目标类、设置方法拦截器enhancer.setSuperclass(Calculator.class);enhancer.setCallback(new CglibInterceptor());//最后通过enhancer.create()创建代理对象将其转换为目标类类型Calculator proxy (Calculator) enhancer.create();//代理类对象调用函数;proxy.add(1,1);proxy.sub(1,1);} }代理模式大致如此是不是so easy轻轻松松的求点赞、收藏⭐
http://www.w-s-a.com/news/12987/

相关文章:

  • 北京市建设管理公司网站长春网站推广排名
  • 西安建站软件获取网站全站代码
  • 个人做网站怎么备案网站建设收费标准渠道
  • 单位做网站注意什么问题如何修改单页网站
  • asp全静态企业网站wordpress文章封面
  • 电白区住房和城乡建设部门户网站免费公司网站模版
  • 做玩游戏任务得q币的网站如何制作自己的公司内部网站
  • 网站优化自己可以做吗非官方网站建设
  • 厦门邮件网站点击网站
  • 网络推广网站的方法亳州网站制作公司
  • 网站域名主机空间区别广告设计专业前景
  • 新手做啥网站好dedecms网站的源码如何安装
  • 哪些网站是用iframe免费网站域名查询
  • 自己开的网站 可以做代销吗百度查找相似图片
  • 网站建设设计作业网站备案渝
  • 中国重庆网站建设福州短视频seo获客
  • 遵义官网网站建设网站移动端开发公司
  • 宜春网站推广优化电子商务网站建设收益举例
  • 游戏网站开发实验报告装修平台哪家好
  • 外贸自己建网站小红门网站建设
  • 中国著名的做网站渗透设计规范网站
  • 公司网站备案多少钱推特最新消息今天
  • 网站关键词设置代码seo搜索优化 指数
  • 做网站卖东西送上门做暧暧xoxo网站
  • 网站网站设计公司网站维护运营好做吗
  • 照片做成视频的软件seo两个域名一个网站有影响吗
  • 制作动画的网站河南省住房城乡建设门户网站
  • 网站推广原则做网站的那个语言好
  • 潍坊网站建设怎样商品网站建设设计思路
  • 建网站公司是如何赚钱南昌营销网站公司哪家好