一文吃透 Spring 中的 AOP 编程

news/2024/4/26 1:42:07/文章来源:https://blog.csdn.net/hh867308122/article/details/129147900

在这里插入图片描述

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。
🍎个人主页:Java Fans的博客
🍊个人信条:不迁怒,不贰过。小知识,大智慧。
💞当前专栏:SSM 框架从入门到精通
✨特色专栏:国学周更-心性养成之路
🥭本文内容:一文吃透 Spring 中的 AOP 编程

文章目录

    • AOP 概述
    • AOP 实现分类
    • AOP 术语
    • 基于 Aspectj 实现 AOP 操作
      • 第一版:基于xml(aop:config)配置文件
      • 第二版:基于xml(aop:aspect)配置文件
      • 第三版:基于注解实现通知

在这里插入图片描述

AOP 概述

AOPAspect Oriented Programming 的缩写,是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOPOOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型

AOP 可以分离业务代码和关注点代码(重复代码),在执行业务代码时,动态的注入关注点代码。切面就是关注点代码形成的类。Spring AOP 中的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口

在这里插入图片描述

AOP 实现分类

AOP 要达到的效果是,保证开发者不修改源代码的前提下,去为系统中的业务组件添加某种通用功能,按照 AOP 框架修改源代码的时机,可以将其分为两类:

  • 静态 AOP 实现, AOP 框架在编译阶段对程序源代码进行修改,生成了静态的 AOP 代理类(生成的 *.class 文件已经被改掉了,需要使用特定的编译器),比如 AspectJ。
  • 动态 AOP 实现, AOP 框架在运行阶段对动态生成代理对象(在内存中以 JDK 动态代理,或 CGlib 动态地生成 AOP 代理类),如 SpringAOP

AOP 术语

  • 连接点(JointPoint)与切入点匹配的执行点,在程序整个执行流程中,可以织入切面的位置,方法的执行前后,异常抛出的位置

  • 切点(PointCut)在程序执行流程中,真正织入切面的方法。

  • 切面(ASPECT)切点+通知就是切面

  • 通知(Advice)切面必须要完成的工作,也叫增强。即,它是类中的一个方法,方法中编写织入的代码。
    前置通知 后置通知
    环绕通知 异常通知
    最终通知

  • 目标对象(Target)被织入通知的对象

  • 代理对象(Proxy)目标对象被织入通知之后创建的新对象

通知的类型

Spring 方面可以使用下面提到的五种通知工作:

通知描述
前置通知在一个方法执行之前,执行通知。
最终通知在一个方法执行之后,不考虑其结果,执行通知。
后置通知在一个方法执行之后,只有在方法成功完成时,才能执行通知。
异常通知在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
环绕通知在一个方法调用之前和之后,执行通知。

基于 Aspectj 实现 AOP 操作

基于 Aspectj 实现 AOP 操作,经历了下面三个版本的变化,注解版是我们最常用的。

切入点表达式

作用:声明对哪个类中的哪个方法进行增强

语法:

execution([访问权限修饰符] 返回值 [ 类的全路径名 ] 方法名 (参数列表)[异常])

  • 访问权限修饰符:

    可选项,不写就是四个权限都包含

    写public就表示只包括公开的方法

  • 返回值类型

    必填项 * 标识返回值任意

  • 全限定类名

    可选项,两个点 … 表示当前包以及子包下的所有类,省略表示所有类

  • 方法名

    必填项 * 表示所有的方法 set*表示所有的set方法

  • 形参列表

    必填项

    ()表示没有参数的方法

    (…)参数类型和参数个数随意的方法

    (*)只有一个参数的方法

    (*,String) 第一个参数类型随意,第二个参数String类型

  • 异常信息

    可选项 省略时标识任何异常信息

在这里插入图片描述

第一版:基于xml(aop:config)配置文件

使用 Spring AOP 接口方式实现 AOP, 可以通过自定义通知来供 Spring AOP 识别对应实现的接口是:

  1. 前置通知:MethodBeforeAdvice
  2. 返回通知:AfterReturningAdvice
  3. 异常通知:ThrowsAdvice
  4. 环绕通知:MethodInterceptor

实现步骤:

1、定义业务接口

/*** 使用接口方式实现AOP, 默认通过JDK的动态代理来实现. 非接口方式, 使用的是cglib实现动态代理*/package cn.kgc.spring05.entity;public interface Teacher {String teachOnLine(String course);String teachOffLine(Integer course);
}

2、定义实现类

package cn.kgc.spring05.entity;public class TeacherA implements Teacher{@Overridepublic String teachOnLine(String course) {System.out.println("TeacherA开始"+course+"课程线上教学");if(course.equals("java")){throw new RuntimeException("入门到放弃!");}return course+"课程线上教学";}@Overridepublic String teachOffLine(Integer course) {System.out.println("TeacherA开始"+course+"课程线下教学");return course+"课程线下教学";}
}

3、实现接口定义通知类

前置通知类

package cn.kgc.spring05.advice;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;//前置通知
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("------------spring aop 前置通知------------");}
}

后置通知类

package cn.kgc.spring05.advice;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class MyAfterReturnAdvice implements AfterReturningAdvice {@Overridepublic void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("------------spring aop 后置通知------------");}
}

4、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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--托管通知--><bean id="after" class="cn.kgc.spring05.advice.MyAfterReturnAdvice"></bean><bean id="before" class="cn.kgc.spring05.advice.MyMethodBeforeAdvice"></bean><bean id="teacherA" class="cn.kgc.spring05.entity.TeacherA"></bean><!--AOP的配置--><aop:config><!--切点表达式--><aop:pointcut id="pt" expression="execution(* *(..))"/><aop:advisor advice-ref="before" pointcut-ref="pt"></aop:advisor><aop:advisor advice-ref="after" pointcut-ref="pt"></aop:advisor></aop:config>
</beans>

5、测试

package cn.kgc.spring05;import cn.kgc.spring05.entity.Teacher;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/*** Unit test for simple App.*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config.xml")
public class AppTest
{@AutowiredTeacher teacher;@Testpublic void teachOnLine() {System.out.println(teacher.getClass());String s = teacher.teachOnLine("java");System.out.println("s = " + s);}
}

6、运行结果

在这里插入图片描述

第二版:基于xml(aop:aspect)配置文件

基于 xml(aop:config) 配置文件的方式,增加几个通知,就会创建几个通知类,那我们能否将这些通知类写在一个类中呢?下面就让我来带你们找到解决之法!

配置 AspectJ 标签解读表

在这里插入图片描述

实现步骤:

1、定义业务接口

/*** 使用接口方式实现AOP, 默认通过JDK的动态代理来实现. 非接口方式, 使用的是cglib实现动态代理*/package cn.kgc.spring05.entity;public interface Teacher {String teachOnLine(String course);String teachOffLine(Integer course);
}

2、定义实现类

package cn.kgc.spring05.entity;public class TeacherA implements Teacher{@Overridepublic String teachOnLine(String course) {System.out.println("TeacherA开始"+course+"课程线上教学");if(course.equals("java")){throw new RuntimeException("入门到放弃!");}return course+"课程线上教学";}@Overridepublic String teachOffLine(Integer course) {System.out.println("TeacherA开始"+course+"课程线下教学");return course+"课程线下教学";}
}

3、实现接口定义通知类

package cn.kgc.spring05.advice;public class AllAdvice {public void before(){System.out.println("------------前置通知--------------");}public void afterReturning(){System.out.println("------------后置通知--------------");}public void afterThrowing(){System.out.println("------------异常通知--------------");}public void after(){System.out.println("------------最终通知--------------");}public void around(){System.out.println("------------环绕通知--------------");}
}

4、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.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--托管通知--><bean id="all" class="cn.kgc.spring05.advice.AllAdvice"></bean><bean id="teacherA" class="cn.kgc.spring05.entity.TeacherA"></bean><!--AOP的配置--><aop:config><!--切点表达式--><aop:pointcut id="pt" expression="execution(* *(String))"/><aop:aspect ref="all"><aop:before method="before" pointcut-ref="pt"></aop:before><aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning><aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing><aop:after method="after" pointcut-ref="pt"></aop:after>
<!--            <aop:around method="around" pointcut-ref="pt"></aop:around>--></aop:aspect></aop:config>
</beans>

5、测试

package cn.kgc.spring05.advice;import cn.kgc.spring05.entity.Teacher;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config2.xml")
public class AllAdviceTest{@AutowiredTeacher teacher;@Testpublic void test01() {System.out.println(teacher.getClass());String s = teacher.teachOnLine("java");System.out.println("s = " + s);}
}

6、运行结果

在这里插入图片描述

第三版:基于注解实现通知

  • 常用 “通知” 注解如下:

    @Aspect 注解将此类定义为切面。
    @Before 注解用于将目标方法配置为前置增强(前置通知)。
    @AfterReturning 注解用于将目标方法配置为后置增强(后置通知)。
    @Around 定义环绕增强(环绕通知)
    @AfterThrowing 配置异常通知
    @After 也是后置通知,与 @AfterReturning 很相似,区别在于 @AfterReturning 在方法执行完毕后进行返回,可以有返回值。@After 没有返回值。

实现步骤:

1、定义业务接口

/*** 使用接口方式实现AOP, 默认通过JDK的动态代理来实现. 非接口方式, 使用的是cglib实现动态代理*/package cn.kgc.spring05.entity;public interface Teacher {String teachOnLine(String course);String teachOffLine(Integer course);
}

2、定义注解

package cn.kgc.spring05.advice;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnoAdvice {
}

3、定义实现类

package cn.kgc.spring05.entity;import cn.kgc.spring05.advice.AnnoAdvice;
import org.springframework.stereotype.Component;@Component
public class TeacherA implements Teacher{@Override@AnnoAdvicepublic String teachOnLine(String course) {System.out.println("TeacherA开始"+course+"课程线上教学");if(course.equals("java")){throw new RuntimeException("入门到放弃!");}return course+"课程线上教学";}@Override@AnnoAdvicepublic String teachOffLine(Integer course) {System.out.println("TeacherA开始"+course+"课程线下教学");return course+"课程线下教学";}
}

4、实现接口定义切面类

首先在类上面添加 @Aspect 注解,将该类转化为切面类,再在类中的各个方法上面使用各自的 “通知” 注解即可实现。

package cn.kgc.spring05.advice;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect
public class AllAdvice {@Pointcut("@annotation(AnnoAdvice)")public void point(){}@Before("point()")public void before(){System.out.println("------------前置通知--------------");}@AfterReturning("point()")public void afterReturning(){System.out.println("------------后置通知--------------");}@AfterThrowing("point()")public void afterThrowing(){System.out.println("------------异常通知--------------");}@After("point()")public void after(){System.out.println("------------最终通知--------------");}@Around("point()")public Object aroundAdvice(ProceedingJoinPoint joinPoint){Object proceed = null;try {System.out.println("----------spring aop 环绕 前通知-----------");proceed = joinPoint.proceed();System.out.println("----------spring aop 环绕 后通知-----------");} catch (Throwable throwable) {throwable.printStackTrace();System.out.println("----------spring aop 环绕 异常通知-----------");}finally {System.out.println("----------spring aop 环绕 最终通知-----------");}return proceed;}
}

5、XML 配置方式

开启包扫描和aspectj自动代理

<?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"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启包扫描--><context:component-scan base-package="cn.kgc.spring05"></context:component-scan><!--开启aspectj自动代理--><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

6、测试

package cn.kgc.spring05.advice;import cn.kgc.spring05.entity.Teacher;
import junit.framework.TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring-config3.xml")
public class AllAdviceTest{@AutowiredTeacher teacher;@Testpublic void test01() {System.out.println(teacher.getClass());String s = teacher.teachOnLine("html");System.out.println("s = " + s);}
}

7、运行效果

在这里插入图片描述


  码文不易,本篇文章就介绍到这里,如果想要学习更多Java系列知识点击关注博主,博主带你零基础学习Java知识。与此同时,对于日常生活有困扰的朋友,欢迎阅读我的第四栏目:《国学周更—心性养成之路》,学习技术的同时,我们也注重了心性的养成。

在这里插入图片描述

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

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

相关文章

【C++】二叉搜索树的模拟实现

一、概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值它的左右子树也分别…

开源ZYNQ AD9361软件无线电平台

&#xff08;1&#xff09; XC7Z020-CLG400 &#xff08;2&#xff09; AD9363 &#xff08;3&#xff09; 单发单收&#xff0c;工作频率400MHz-2.7GHz &#xff08;4&#xff09; 发射带PA&#xff0c;最大输出功率约20dbm &#xff08;5&#xff09; 接收带LNA&#xff0c;低…

Linux学习(9.1)文件系统的简单操作

以下内容转载自鸟哥的Linux私房菜 原文&#xff1a;鸟哥的 Linux 私房菜 -- Linux 磁盘与文件系统管理 (vbird.org) 磁盘与目录的容量 df&#xff1a;列出文件系统的整体磁盘使用量&#xff1b;du&#xff1a;评估文件系统的磁盘使用量(常用在推估目录所占容量) df du 实体…

微信小程序 《新闻列表》 案例

目录&#xff1a;一&#xff0c;步骤。要求1&#xff1a;主页头部的轮播图要求2&#xff1a;中间内容上的信息案列排版。要求3&#xff1a;上拉加载内容。要求4&#xff1a;在信息加载完成后&#xff0c;给用户提示二&#xff0c;过程中要注意的几点。1.在微信小程序中&#xf…

HNU工训中心:电子开关与信号隔离

工训中心的牛马实验 1.实验目的&#xff1a; 1) 认识三极管和MOS管构成三端电子开关电路&#xff1b; 认识信号隔离的继电器和光电隔离方式。 2) 认识施密特触发器&#xff0c;掌握一种波形变换方法。 3) 实现一种脉冲波形发生器。 2.实验资源 HBE硬件基础电路实验箱、示波…

第八节 构造器和this关键字、封装

构造器的作用 定义在类中的&#xff0c;可以用于初始化一个类的对象&#xff0c;并返回对象的地址。 构造器的注意事项 1.任何类定义出来&#xff0c;默认就自带了无参数构造器&#xff0c;写不写都有。 2.一旦定义了有参数构造器&#xff0c;那么无参数构造器就没有了&#xf…

Adversarially-Aware Robust Object Detector

目标检测作为计算机视觉的基本任务&#xff0c;随着深度神经网络的出现而取得了显著的进展。然而&#xff0c;很少有研究在各种现实场景中探索目标检测器抵抗对抗攻击的对抗鲁棒性。探测器已经受到不可察觉的扰动的极大挑战&#xff0c;在干净图像上的性能急剧下降&#xff0c;…

记录pytorch安装 windows10 64位--(可选)安装paddleseg

安装完paddlepaddle之后&#xff0c;就可以安装paddleseg了。一、安装Git可以参考这个网址&#xff1a;https://blog.csdn.net/u010348546/article/details/124280236windows下安装git和gitbash安装教程二、安装paddleseghttps://github.com/PaddlePaddle/PaddleSeg记得翻墙啊这…

Ubuntu 交叉编译工具链安装

Ubuntu 交叉编译工具链安装 1 交叉编译器安装 ARM 裸机、Uboot 移植、Linux 移植这些都需要在 Ubuntu 下进行编译&#xff0c;编译就需要编译器&#xff0c;我们在第三章“Linux C 编程入门”里面已经讲解了如何在 Liux 进行 C 语言开发&#xff0c;里面使用 GCC 编译器进行代…

试题 算法训练 JOE的矩阵

问题描述 最近JOE又在线性代数的模拟考中拿满分了&#xff0c;这直接导致了JOE对于计算矩阵的热情急剧下降&#xff0c;所以JOE希望能有这样一个程序能帮助他计算矩阵的秩。 输入格式 第一行&#xff0c;两个数n,m&#xff0c;表示矩阵是n*m的。   下面共n行&#xff0c;每行…

Airbnb(三) Managing Diversity in Airbnb Search 搜索多样性

abstract 搜索系统中一个长期的问题是结果多样性。从产品角度讲&#xff0c;给用户多种多样的选择&#xff0c;有助于提升用户体验及业务指标。 多样性需求和模型的目标是相矛盾的&#xff0c;因为传统ctr模型是 point wise&#xff0c;只看单个相关性不管相邻之间item差异。 …

设计模式-笔记

文章目录七大原则单例模式桥模式 bridge观察者模式 observer责任链模式 Chain of Responsibility命令模式 Command迭代器模式 Iterator中介者模式 Mediator享元模式 Flyweight Pattern组合模式 composite装饰模式 Decorator外观模式 Facade简单工厂模式工厂方法模式工厂抽象模式…

数学小课堂:无穷小(平均速度和瞬间速度的关系)

文章目录 引言I 速度1.1 平均速度1.2 瞬间速度(某一时刻特定的速度)1.3 解释飞箭是静止的悖论II 导数2.1 概念2.2 导数的现实影响2.3 微积分的意义III 无穷小3.1 贝克莱挑战牛顿(无穷小悖论)3.2 无穷小的定义引言 柯西和魏尔斯特拉斯给出的无穷小的定义: 它不是零;它的绝对…

【GUI】Robo 3T(Studio 3T Free) for Mongodb安装与使用教程

下载 robo 3T现已更名为studio 3T free&#xff0c;官网即可下载 studio 3T free下载地址 安装 mac电脑下载的是dmg安装包&#xff0c;直接正常安装即可&#xff0c;windows电脑也是一样的&#xff0c;不需要配置环境&#xff0c;安装即可使用。&#xff08;前提是你已经安装…

什么是接口测试,我们如何实现接口测试?

1. 什么是接口测试 顾名思义&#xff0c;接口测试是对系统或组件之间的接口进行测试&#xff0c;主要是校验数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及相互逻辑依赖关系。其中接口协议分为HTTP,WebService,Dubbo,Thrift,Socket等类型&#xff0c;测试类型又主…

SkyWalking简介和安装

APM系统 早期的监控系统功能比较单一&#xff0c;主要以监控CPU、内存、网络、I/O等基础设置为主&#xff08;cacti、nagios&#xff09; 后来随着中间件技术的不断发展&#xff0c;监控系统也开始监控缓存、数据库、MQ等各种基础组件的性能&#xff08;zabbix、prommethus&a…

【MinIO】文件断点续传和分块合并

【MinIO】文件断点续传和分块合并 文章目录【MinIO】文件断点续传和分块合并0. 准备工作1. 检查文件是否存在1.1 定义接口1.2 编写实现方法2. 检查分块文件是否存在2.1 定义接口2.2 编写实现方法3. 上传分块文件接口3.1 定义接口3.2 编写实现方法4. 合并分块文件接口4.1 定义接…

Python - Opencv应用实例之CT图像检测边缘和内部缺陷

Python - Opencv应用实例之CT图像检测边缘和内部缺陷 将传统图像处理处理算法应用于CT图像的边缘检测和缺陷检测,想要实现效果如下: 关于图像处理算法,主要涉及的有:灰度、阈值化、边缘或角点等特征提取、灰度相似度变换,主要偏向于一些2D的几何变换、涉及图像矩阵的一些统…

java中使用protobuf总结

基本没怎么接触过java编程&#xff0c;别的团队发过来一个用java编写的存储pb的文件&#xff0c;让拆分和解析&#xff0c;硬着头皮做一下&#xff0c;在此将步骤做个记录&#xff1a;下载安装protobufhttps://github.com/protocolbuffers/protobuf/tags?afterv3.6.1.2编译pro…

AI/CV大厂笔试LeetCode高频考题之基础核心知识点

AI/CV互联网大厂笔试LeetCode高频考题之基础核心知识点算法复习1、二叉树的遍历2、回溯算法3、二分搜索4、滑动窗口算法题5、经典动态规划6、动态规划答疑篇6.1、总结一下如何找到动态规划的状态转移关系7、编辑距离8、戳气球问题9、最长公共子序列 Longest Common Subsequence…