Spring高手之路19——Spring AOP注解指南

文章目录

  • 1. 背景
  • 2. 基于AspectJ注解来实现AOP
  • 3. XML实现和注解实现AOP的代码对比
  • 4. AOP通知讲解
  • 5. AOP时序图

1. 背景

  在现代软件开发中,面向切面编程(AOP)是一种强大的编程范式,允许开发者跨越应用程序的多个部分定义横切关注点(如日志记录、事务管理等)。本文将介绍如何在Spring框架中通过AspectJ注解以及对应的XML配置来实现AOP,在不改变主业务逻辑的情况下增强应用程序的功能。

2. 基于AspectJ注解来实现AOP

对于一个使用MavenSpring项目,需要在pom.xml中添加以下依赖:

<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.10</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.9.6</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version></dependency>
</dependencies>

确保版本号与使用的Spring版本相匹配,可以自行调整。

  1. 创建业务逻辑接口MyService
package com.example.demo.aop;public interface MyService {void performAction();
}
  1. 创建业务逻辑类MyServiceImpl.java
package com.example.demo.aop;import org.springframework.stereotype.Service;@Service
public class MyServiceImpl implements MyService {@Overridepublic void performAction() {System.out.println("Performing an action in MyService");}
}
  1. 定义切面

创建切面类MyAspect.java,并使用注解定义切面和通知:

package com.example.demo.aop;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class MyAspect {@Before("execution(* com.example.demo.aop.MyServiceImpl.performAction(..))")public void logBeforeAction() {System.out.println("Before performing action");}
}

  @Aspect注解是用来标识一个类作为AspectJ切面的一种方式,这在基于注解的AOP配置中是必需的。它相当于XML配置中定义切面的方式,但使用注解可以更加直观和便捷地在类级别上声明切面,而无需繁琐的XML配置。

  1. 配置Spring以启用注解和AOP

  创建一个Java配置类来代替XML配置,使用@Configuration注解标记为配置类,并通过@ComponentScan注解来启用组件扫描,通过@EnableAspectJAutoProxy启用AspectJ自动代理:

package com.example.demo.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
}

  @EnableAspectJAutoProxy注解在Spring中用于启用对AspectJ风格的切面的支持。它告诉Spring框架去寻找带有@Aspect注解的类,并将它们注册为Spring应用上下文中的切面,以便在运行时通过代理方式应用这些切面定义的通知(Advice)和切点(Pointcuts)。

  如果不写@EnableAspectJAutoProxySpring将不会自动处理@Aspect注解定义的切面,则定义的那些前置通知(@Before)、后置通知(@After@AfterReturning@AfterThrowing)和环绕通知(@Around)将不会被自动应用到目标方法上。这意味着定义的AOP逻辑不会被执行,失去了AOP带来的功能增强。

  @Before 注解定义了一个前置通知(Advice),它会在指定方法执行之前运行。切点表达式execution(* com.example.demo.aop.MyServiceImpl.performAction(..))精确地定义了这些连接点的位置。在这个例子中,切点表达式指定了MyServiceImpl类中的performAction方法作为连接点,而@Before注解标识的方法(logBeforeAction)将在这个连接点之前执行,即logBeforeAction方法(前置通知)会在performAction执行之前被执行。

  1. 创建主类和测试AOP功能

主程序如下:

package com.example.demo;import com.example.demo.aop.MyService;
import com.example.demo.config.AppConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class DemoApplication {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);MyService service = context.getBean(MyService.class);service.performAction();}
}

运行结果如下:

在这里插入图片描述

3. XML实现和注解实现AOP的代码对比

  对于上面的代码,我们将原有基于注解的AOP配置改写为完全基于XML的形式,方便大家对比。首先需要移除切面类和业务逻辑类上的所有Spring相关注解,然后在XML文件中配置相应的beanAOP逻辑。

移除注解
首先,我们移除业务逻辑类和切面类上的所有注解。

MyService.java (无变化,接口保持原样):

package com.example.demo.aop;public interface MyService {void performAction();
}

MyServiceImpl.java (移除@Service注解):

package com.example.demo.aop;public class MyServiceImpl implements MyService {@Overridepublic void performAction() {System.out.println("Performing an action in MyService");}
}

MyAspect.java (移除@Aspect和@Component注解,同时去掉方法上的@Before注解):

package com.example.demo.aop;public class MyAspect {public void logBeforeAction() {System.out.println("Before performing action");}
}

XML配置

接下来,删除AppConfig配置类,在SpringXML配置文件中定义beansAOP配置。

applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 定义业务逻辑bean --><bean id="myService" class="com.example.demo.aop.MyServiceImpl"/><!-- 定义切面 --><bean id="myAspect" class="com.example.demo.aop.MyAspect"/><!-- AOP配置 --><aop:config><aop:aspect id="aspect" ref="myAspect"><aop:pointcut id="serviceOperation" expression="execution(* com.example.demo.aop.MyService.performAction(..))"/><aop:before pointcut-ref="serviceOperation" method="logBeforeAction"/></aop:aspect></aop:config>
</beans>

  在这个XML配置中,我们手动注册了MyServiceImplMyAspect作为beans,并通过<aop:config>元素定义了AOP逻辑。我们创建了一个切点serviceOperation,用于匹配MyService.performAction(..)方法的执行,并定义了一个前置通知,当匹配的方法被调用时,MyAspectlogBeforeAction方法将被执行。

主类和测试AOP功能

主类DemoApplication的代码不需要改变,只是在创建ApplicationContext时使用XML配置文件而不是Java配置类:

package com.example.demo;import com.example.demo.aop.MyService;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class DemoApplication {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");MyService service = context.getBean(MyService.class);service.performAction();}
}

运行结果是一样的

在这里插入图片描述

4. AOP通知讲解

  在Spring AOP中,通知(Advice)定义了切面(Aspect)在目标方法调用过程中的具体行为。Spring AOP支持五种类型的通知,它们分别是:前置通知(Before)、后置通知(After)、返回通知(After Returning)、异常通知(After Throwing)和环绕通知(Around)。通过使用这些通知,开发者可以在目标方法的不同执行点插入自定义的逻辑。

  • @Before(前置通知)

前置通知是在目标方法执行之前执行的通知,通常用于执行一些预处理任务,如日志记录、安全检查等。

@Before("execution(* com.example.demo.aop.MyServiceImpl.performAction(..))")
public void logBeforeAction() {System.out.println("Before performing action");
}
  • @AfterReturning(返回通知)

返回通知在目标方法成功执行之后执行,可以访问方法的返回值。

@AfterReturning(pointcut = "execution(* com.example.demo.aop.MyServiceImpl.performAction(..))", returning = "result")
public void logAfterReturning(Object result) {System.out.println("Method returned value is : " + result);
}

  这里在@AfterReturning注解中指定returning = "result"时,Spring AOP框架将目标方法的返回值传递给切面方法的名为result的参数,因此,切面方法需要有一个与之匹配的参数,类型兼容目标方法的返回类型。如果两者不匹配,Spring在启动时会抛出异常,因为它无法将返回值绑定到切面方法的参数。

  • @AfterThrowing(异常通知)

异常通知在目标方法抛出异常时执行,允许访问抛出的异常。

@AfterThrowing(pointcut = "execution(* com.example.demo.aop.MyServiceImpl.performAction(..))", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {String methodName = joinPoint.getSignature().getName();System.out.println("@AfterThrowing: Exception in method: " + methodName + "; Exception: " + ex.toString());
}

  在@AfterThrowing注解的方法中包含JoinPoint参数是可选的,当想知道哪个连接点(即方法)引发了异常的详细信息时非常有用,假设有多个方法可能抛出相同类型的异常,而我们想在日志中明确指出是哪个方法引发了异常。通过访问JoinPoint提供的信息,可以记录下引发异常的方法名称和其他上下文信息,从而使得日志更加清晰和有用。

  • @After(后置通知)

后置通知在目标方法执行之后执行,无论方法执行是否成功,即便发生异常,仍然会执行。它类似于finally块。

@After("execution(* com.example.demo.aop.MyServiceImpl.performAction(..))")
public void logAfter() {System.out.println("After performing action");
}
  • @Around(环绕通知)

环绕通知围绕目标方法执行,可以在方法调用前后执行自定义逻辑,同时决定是否继续执行目标方法。环绕通知提供了最大的灵活性和控制力。

@Around("execution(* com.example.demo.aop.MyServiceImpl.performAction(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before method execution");Object result = joinPoint.proceed(); // 继续执行目标方法System.out.println("After method execution");return result;
}

接下来,我们来演示一下,全部代码如下:

服务接口(MyService.java):

package com.example.demo.aop;public interface MyService {String performAction(String input);
}

服务实现(MyServiceImpl.java):

修改performAction方法,使其在接收到特定输入时抛出异常

package com.example.demo.aop;import org.springframework.stereotype.Service;@Service
public class MyServiceImpl implements MyService {@Overridepublic String performAction(String input) {System.out.println("Performing action with: " + input);if ("error".equals(input)) {throw new RuntimeException("Simulated error");}return "Processed " + input;}
}

完整的切面类(包含所有通知类型)

切面类(MyAspect.java) - 保持不变,确保包含所有类型的通知:

package com.example.demo.aop;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class MyAspect {@Before("execution(* com.example.demo.aop.MyService.performAction(..))")public void beforeAdvice(JoinPoint joinPoint) {System.out.println("@Before: Before calling performAction");}@After("execution(* com.example.demo.aop.MyService.performAction(..))")public void afterAdvice(JoinPoint joinPoint) {System.out.println("@After: After calling performAction");}@AfterReturning(pointcut = "execution(* com.example.demo.aop.MyService.performAction(..))", returning = "result")public void afterReturningAdvice(JoinPoint joinPoint, Object result) {System.out.println("@AfterReturning: Method returned value is : " + result);}@AfterThrowing(pointcut = "execution(* com.example.demo.aop.MyService.performAction(..))", throwing = "ex")public void afterThrowingAdvice(JoinPoint joinPoint, Throwable ex) {String methodName = joinPoint.getSignature().getName();System.out.println("@AfterThrowing: Exception in method: " + methodName + "; Exception: " + ex.toString());}@Around("execution(* com.example.demo.aop.MyService.performAction(..))")public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("@Around: Before method execution");Object result = null;try {result = proceedingJoinPoint.proceed();} catch (Throwable throwable) {// 如果执行方法出现异常,打印这里System.out.println("@Around: Exception in method execution");throw throwable;}// 如果执行方法正常,打印这里System.out.println("@Around: After method execution");return result;}
}

这里要强调几点:

  1. @Around环绕通知常见用例是异常捕获和重新抛出。在这个例子中,我们通过ProceedingJoinPointproceed()方法调用目标方法。如果目标方法执行成功,记录执行后的消息并返回结果。如果在执行过程中发生异常,在控制台上打印出异常信息,然后重新抛出这个异常。这样做可以确保异常不会被吞没,而是可以被上层调用者捕获或由其他异常通知处理。

  2. @AfterThrowing注解标明这个通知只有在目标方法因为异常而终止时才会执行。throwing属性指定了绑定到通知方法参数上的异常对象的名称。这样当异常发生时,异常对象会被传递到afterThrowingAdvice方法中,方法中可以对异常进行记录或处理。

  3. @AfterThrowing@AfterReturning通知不会在同一个方法调用中同时执行。这两个通知的触发条件是互斥的。@AfterReturning 通知只有在目标方法成功执行并正常返回后才会被触发,这个通知可以访问方法的返回值。@AfterThrowing 通知只有在目标方法抛出异常时才会被触发,这个通知可以访问抛出的异常对象。

  4. 假设想要某个逻辑总是在方法返回时执行,不管是抛出异常还是正常返回,则考虑放在@After或者@Around通知里执行。

配置类

package com.example.demo.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan("com.example")
@EnableAspectJAutoProxy
public class AppConfig {
}

测试不同情况

为了测试所有通知类型的触发,在主类中执行performAction方法两次:一次传入正常参数,一次传入会导致异常的参数。

主程序如下:

package com.example.demo;import com.example.demo.aop.MyService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class DemoApplication {public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);MyService service = context.getBean(MyService.class);try {// 正常情况System.out.println("Calling performAction with 'test'");service.performAction("test");// 异常情况System.out.println("\nCalling performAction with 'error'");service.performAction("error");} catch (Exception e) {System.out.println("Exception caught in DemoApplication: " + e.getMessage());}}
}

在这个例子中,当performAction方法被第二次调用并传入"error"作为参数时,将会抛出异常,从而触发@AfterThrowing通知。

运行结果如下:

在这里插入图片描述

5. AOP时序图

  这里展示在Spring AOP框架中一个方法调用的典型处理流程,包括不同类型的通知(Advice)的执行时机。

在这里插入图片描述

  1. 客户端调用方法:
  • 客户端(Client)发起对某个方法的调用。这个调用首先被AOP代理(AOP Proxy)接收,这是因为在Spring AOP中,代理负责在真实对象(Target)和外界之间进行中介。
  1. 环绕通知开始 (@Around):
  • AOP代理首先调用切面(Aspect)中定义的环绕通知的开始部分。环绕通知可以在方法执行前后执行代码,并且能决定是否继续执行方法或直接返回自定义结果。这里的“开始部分”通常包括方法执行前的逻辑。
  1. 前置通知 (@Before):
  • 在目标方法执行之前,执行前置通知。这用于在方法执行前执行如日志记录、安全检查等操作。
  1. 执行目标方法:
  • 如果环绕通知和前置通知没有中断执行流程,代理会调用目标对象(Target)的实际方法。
  1. 方法完成:
  • 方法执行完成后,控制权返回到AOP代理。这里的“完成”可以是成功结束,也可以是抛出异常。
  1. 返回通知或异常通知:
  • 返回通知 (@AfterReturning):如果方法成功完成,即没有抛出异常,执行返回通知。这可以用来处理方法的返回值或进行某些后续操作。
  • 异常通知 (@AfterThrowing):如果方法执行过程中抛出异常,执行异常通知。这通常用于异常记录或进行异常处理。
  1. 后置通知 (@After):
  • 独立于方法执行结果,后置通知总是会执行。这类似于在编程中的finally块,常用于资源清理。
  1. 环绕通知结束 (@Around):
  • 在所有其他通知执行完毕后,环绕通知的结束部分被执行。这可以用于执行清理工作,或者在方法执行后修改返回值。
  1. 返回结果:
  • 最终,AOP代理将处理的结果返回给客户端。这个结果可能是方法的返回值,或者通过环绕通知修改后的值,或者是异常通知中处理的结果。

欢迎一键三连~

有问题请留言,大家一起探讨学习

----------------------Talk is cheap, show me the code-----------------------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/21296.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度解析:重庆耶非凡科技有限公司的人力rpo项目

在当今竞争激烈的商业环境中&#xff0c;人力资源项目的成功与否往往决定了一个企业的长远发展。重庆耶非凡科技有限公司作为行业内的佼佼者&#xff0c;其人力资源项目备受瞩目。本文将深入探讨该公司的人力资源项目&#xff0c;特别是其独特的选品师项目和人力RPO服务。 首先…

2024年06月在线IDE流行度最新排名

点击查看最新在线IDE流行度最新排名&#xff08;每月更新&#xff09; 2024年06月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多&#xff0c;人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…

数字光强测量仪OPT3001

外观 参考价格 原理图 频谱 特性 说明 OPT3001 传感器用于测量可见光的密度。传感器的光 谱响应与人眼的视觉响应紧密匹配&#xff0c;其中具有很高的红 外线阻隔。 OPT3001 是一款可如人眼般测量光强的单芯片照度 计。OPT3001 器件兼具精密的频谱响应和较强的 IR 阻隔功能&a…

基于Weaviate构建多模态检索和多模态检索增强(RAG): Building Multimodal Search and RAG

Building Multimodal Search and RAG 本文是学习 https://www.deeplearning.ai/short-courses/building-multimodal-search-and-rag/ 这门课的学习笔记。 What you’ll learn in this course Learn how to build multimodal search and RAG systems. RAG systems enhance an …

在iPhone上恢复已删除的Safari历史记录的最佳方法

您是否正在寻找恢复 iPhone 上已删除的 Safari 历史记录的最佳方法&#xff1f;好吧&#xff0c;这篇文章提供了 4 种在有/无备份的情况下恢复 iPhone 上已删除的 Safari 历史记录的最佳方法。现在按照分步指南进行操作。 iPhone 上的 Safari 历史记录会被永久删除吗&#xff1…

kafka 发送文件二进制流及使用header发送附属信息

文章目录 背景案例发送方接收方 背景 需要使用kafka发送文件二进制以及附属信息 案例 发送方 import org.apache.kafka.clients.producer.KafkaProducer; import org.apache.kafka.clients.producer.ProducerRecord;import java.io.InputStream; import java.nio.charset.S…

Halo DB 魔法之 pg_pcpu_limit

↑ 关注「少安事务所」公众号&#xff0c;欢迎⭐收藏&#xff0c;不错过精彩内容~ 前情回顾 前面已经介绍了“光环”数据库的基本情况和安装办法&#xff0c;今天来介绍一个新话题。 哈喽&#xff0c;国产数据库&#xff01;Halo DB! 三步走&#xff0c;Halo DB 安装指引 ★ Ha…

Java Agent利器

一、JavaAgent技术 1.1 什么是JavaAgent JavaAgent是一种特殊的Java程序&#xff0c;是Instrumentation的客户端。它与普通Java程序通过main方法启动不同&#xff0c;JavaAgent并不是一个可以单独启动的程序&#xff0c;它必须依附在一个Java应用程序&#xff08;JVM&#xf…

java并发常见问题

1.死锁&#xff1a;当两个或多个线程无限期地等待对方释放锁时发生死锁。为了避免这种情况&#xff0c;你应该尽量减少锁定资源的时间&#xff0c;按顺序获取锁&#xff0c;并使用定时锁尝试。 2.竞态条件&#xff1a;当程序的行为依赖于线程的执行顺序或输入数据到达的顺序时…

Lagrange ZK Coprocessor:革新区块链领域的大数据应用

1. 引言 2024年5月11日&#xff0c;Lagrange Labs宣称获得由Founders Fund领投&#xff08;Archetype Ventures, 1kx, Maven11, Fenbushi Capital, Volt Capital, CMT Digital, Mantle Ecosystem Fund和其它天使投资人跟头&#xff09;的1320万美金种子轮融资&#xff0c;致力于…

springboot高校网上选课系统-计算机毕业设计源码85583

摘 要 本论文主要论述了如何使用JAVA语言开发一个高校网上选课系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述高校网上选课系统的当前背景以及系统开发的目…

typescript --object对象类型

ts中的object const obj new Object()Object 这里的Object是Object类型&#xff0c;而不是JavaScript内置的Object构造函数。 这里的Object是一种类型&#xff0c;而Object()构造函数表示一个值。 Object()构造函数的ts代码 interface ObjectConstructor{readonly prototyp…

C++20 范围(Range):简化集合操作

C20 范围&#xff1a;简化集合操作 一、范围&#xff08;Range&#xff09;的目的二、在模板函数中使用范围概念三、投影四、视图五、结论 一、范围&#xff08;Range&#xff09;的目的 在 C20 中&#xff0c;范围概念要求一个对象同时拥有迭代器和结束哨兵。这在标准集合的上…

YOLOv5改进(五)-- 轻量化模型MobileNetv3

文章目录 1、MobileNetV3论文2、代码实现2.1、MobileNetV3-small2.2、MobileNetV3-large 3、运行效果4、目标检测系列文章 1、MobileNetV3论文 Searching for MobileNetV3论文 MobileNetV3代码 MobileNetV3 是 Google 提出的一种轻量级神经网络结构&#xff0c;旨在在移动设备上…

官网上线,一款令人惊艳的文本转语音模型:ChatTTS

近日&#xff0c;一个名为 ChatTTS 文本转语音模型的项目在github上横空出世&#xff0c;一经推出便引发极大关注&#xff0c;短短四天时间&#xff0c;已经狂揽了14.2k的Start量。 ChatTTS是一款专为对话场景设计的支持中英文的文本转语音&#xff08;TTS&#xff09;模型&…

未来已来:Spring Boot引领数据库智能化革命

深入探讨了Spring Boot如何与现代数据库技术相结合&#xff0c;预测并塑造未来的数据访问趋势。本书不仅涵盖了Spring Data JPA的使用技巧&#xff0c;还介绍了云原生数据库的概念&#xff0c;微服务架构下的数据访问策略&#xff0c;以及AI在数据访问层的创新应用。旨在帮助开…

XFeat:速度精度远超superpoint的轻量级图像匹配算法

代码地址&#xff1a;https://github.com/verlab/accelerated_features?tabreadme-ov-file 论文地址&#xff1a;2404.19174 (arxiv.org) XFeat (Accelerated Features)重新审视了卷积神经网络中用于检测、提取和匹配局部特征的基本设计选择。该模型满足了对适用于资源有限设备…

在table中获取每一行scope的值

目的 当前有一份如下数据需要展示在表格中&#xff0c;表格的页面元素套了一个折叠面板&#xff0c;需要循环page_elements中的数据展示出来 错误实践 将template放在了折叠面板中&#xff0c;获取到的scope是空数组 <el-table-column label"页面元素" show-o…

【并发程序设计】15.信号灯(信号量)

15.信号灯(信号量) Linux中的信号灯即信号量是一种用于进程间同步或互斥的机制&#xff0c;它主要用于控制对共享资源的访问。 在Linux系统中&#xff0c;信号灯作为一种进程间通信&#xff08;IPC&#xff09;的方式&#xff0c;与其他如管道、FIFO或共享内存等IPC方式不同&…

分析和设计算法

目录 前言 循环不变式 n位二进制整数相加问题 RAM模型 使用RAM模型分析 代码的最坏情况和平均情况分析 插入排序最坏情况分析 插入排序平均情况分析 设计算法 分治法 总结 前言 循环迭代&#xff0c;分析算法和设计算法作为算法中的三个重要的角色&#xff0c;下面…