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

Spring企业开发核心框架-下

五、Spring AOP面向切面编程

1、场景设定和问题复现

①准备AOP项目

项目名:Spring-aop-annotation

②声明接口

/***       + - * / 运算的标准接口!*/
public interface Calculator {    int add(int i, int j);    int sub(int i, int j);   int mul(int i, int j);    int div(int i, int j);}

③实现接口

/*** 实现计算接口,单纯添加 + - * / 实现! 掺杂其他功能!*/
public class CalculatorPureImpl implements Calculator {    @Overridepublic int add(int i, int j) {    int result = i + j;    return result;}    @Overridepublic int sub(int i, int j) {    int result = i - j;    return result;}    @Overridepublic int mul(int i, int j) {    int result = i * j;    return result;}    @Overridepublic int div(int i, int j) {    int result = i / j;    return result;}
}

④声明带日志接口实现

新需求:需要在每一个方法中,添加控制台输出,输出参数和输出计算后的返回值!

/*** 在每个方法中,输出传入的参数和计算后的返回结果!*/
public class CalculatorLogImpl implements Calculator {    @Overridepublic int add(int i, int j) {    System.out.println("参数是:" + i + "," + j);int result = i + j;System.out.println("方法内部 result = " + result);      return result;}    @Overridepublic int sub(int i, int j) {    System.out.println("参数是:" + i + "," + j);    int result = i - j;    System.out.println("方法内部 result = " + result);return result;}    @Overridepublic int mul(int i, int j) {    System.out.println("参数是:" + i + "," + j);   int result = i * j;    System.out.println("方法内部 result = " + result);    return result;}    @Overridepublic int div(int i, int j) {    System.out.println("参数是:" + i + "," + j);    int result = i / j;   System.out.println("方法内部 result = " + result);        return result;}
}

⑤代码问题分析

1)代码缺陷

  • 对核心业务功能有干扰,导致程序员在开发核心业务功能时分散了精力
  • 附加功能代码重复,分散在各个业务功能方法中,冗余,且不方便统一维护!

2)解决问题

  • 核心就是:解耦。我们需要把附加功能从业务功能代码中抽取出来。将重复的代码统一提取,并且【动态插入】到每个业务方法!

3)技术困难

  • 解决问题的困难:提取重复附加功能代码到一个类中,可以实现但是如何将代码插入到各个方法中?我们不会,我们需要引用新技术!!!
2、解决技术代理模式

① 代理模式

23种设计模式中的一种,属于结构型模式。它的作用就是通过提供一个代理类,让我们在调用目标方法的时候,不再是直视对目标方法进行调用,而是通过代理类间调用。让不属于目标方法核心逻辑的代码从目标方法中剥离出来——解耦。调用目标方法时先调用代理对象的方法,减少对目标方法的调用和打扰,同时让附加功能能够集中在一起也有利于统一维护。

代理场景:

  •  代理:将非核心逻辑剥离出来以后,封装这些非核心逻辑的类、对象、方法。(中介)
    • 动词:指做代理这个动作,或这项工作
    • 名词:扮演代理这个角色的类、对象、方法
  • 目标:被代理“套用”了非核心逻辑代码的类、对象、方法。代理在开发中实现的方式具体有两种:静态代理,动态代理。

② 静态代理

主动创建代理类:

public class CalculatorStaticProxy implements Calculator {    // 将被代理的目标对象声明为成员变量private Calculator target;    public CalculatorStaticProxy(Calculator target) {this.target = target;}    @Overridepublic int add(int i, int j) {    // 附加功能由代理类中的代理方法来实现System.out.println("参数是:" + i + "," + j);    // 通过目标对象来实现核心业务逻辑int addResult = target.add(i, j);   System.out.println("方法内部 result = " + result);   return addResult;}……

静态代理确实实现了解耦,但是由于代码都写死了,完全不具备任何的灵活性。就拿日志功能来说,将其他地方也需要附加日志,那还得再声明更多个静态代理类,那就生产了大量重复代码,日志功能还是分散的,没有统一管理。

③ 动态代理

  • JDK动态代理:JDK原生的实现方式,需要被代理的目标类必须实现接口!它会根据目标类的接口动态生成一个代理对象!代理对象和目标对象有相同的接口!(拜把子)
  • cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口!(认干爹)

代理工程:基于jdk代理技术,生成代理对象

public class ProxyFactory<T> {//目标对象。具体什么类型由调用者指定private T target;public ProxyFactory(T target) {this.target = target;}public T getProxy(){//1、获取目标对象的类加载器ClassLoader classLoader = target.getClass().getClassLoader();//2、获取目标对象所实现的所有对象Class<?>[] interfaces = target.getClass().getInterfaces();//1、JDK动态代理方式:T o = (T)Proxy.newProxyInstance(classLoader, interfaces, new MyInvocationHandler());return o;}public class MyInvocationHandler implements InvocationHandler{@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//反射角度:method是目标方法,args是目标方法执行时所需要的参数。System.out.println("日志功能,"+method.getName()+"方法执行了,参数为:"+ Arrays.toString(args));//核心:目标方法Object result = method.invoke(target, args);System.out.println("日志功能,"+method.getName()+"方法执行结束,结果为:"+ result);return result;}}
}

④ 代理总结

代理方式可以解决附加功能代码干扰核心代码和不方便统一维护的问题!

它主要是将附加功能代码提取到代理中执行,不干扰目标核心代码。但是我们也发现,无论使用静态代理和动态代理,程序员的工作都比较繁琐,需要自己编写代理工厂等。但是,提前剧透,我们在实际开发中,不需要编写代理代码,我们可以使用SpringAOP框架,它会简化代理的实现!

3、面向切面编程思维(AOP)

1)面向切面编程思想AOP

AOP:Aspect Oriented Programming 面向切面编程

AOP可以说是OOP的补充和完善。OOP引入封装、继承、多态等概念来建立一种对象层次结构,用于模拟公共行为的一个集合。不过OOP允许开发者定义纵向的关系,但并不适合定义横向的关系,例如日志功能。日志代码往往横向地散布在所有对象层次中,而与它对应的对象的核心功能毫无关系对于其他类型的代码,如安全性、异常处理和透明的持续性也都如此,这种散布在各处的无关的代码被称为横切,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

http://www.lryc.cn/news/388292.html

相关文章:

  • X射线底片焊缝缺陷检测
  • 直播的js代码debug解析找到protobuf消息的定义
  • 详细学习es6扩展运算符
  • HEC-HMS水文模型教程
  • Spring Cloud LoadBalancer基础入门与应用实践
  • layui在表格中嵌入上传按钮,并修改上传进度条
  • 14-10 AIGC 项目生命周期——第一阶段
  • 经典小游戏(一)C实现——三子棋
  • 如何利用AI生成可视化图表(统计图、流程图、思维导图……)免代码一键绘制图表
  • Firefox 编译指南2024 Windows10-使用Git 管理您的Firefox(五)
  • ubuntu 18 虚拟机安装(1)
  • Github 上 Star 数最多的大模型应用基础服务 Dify 深度解读(一)
  • XStream导出xml文件
  • 陪诊小程序搭建:构建便捷医疗陪诊服务的创新实践
  • 0139__TCP协议
  • 家政小程序的开发,带动市场快速发展,提高家政服务质量
  • JavaScript高级程序设计(第四版)--学习记录之对象、类与面向对象编程(下)
  • PDF 生成(5)— 内容页支持由多页面组成
  • day 51 115.不同的子序列 583. 两个字符串的删除操作 72. 编辑距离
  • http包详解
  • Reqable实战系列:Flutter移动应用抓包调试教程
  • 乾元通渠道商中标吴忠市自然灾害应急能力提升项目
  • 护网蓝队面试
  • 【高考志愿】金融学
  • 返利App的用户行为分析与数据驱动决策
  • python基础:高级数据类型:集合
  • idk17配置
  • Java实现日志全链路追踪.精确到一次请求的全部流程
  • 你敢相信吗,AI绘画正在逐渐取代你的工作!
  • 博途PLC轴工艺对象随动误差监视功能