SAP ABAP性能优化

1.前言

ABAP作为SAP的专用的开发语言,衡量其性能的指标主要有以下两个方面:

响应时间:对于某项特定的业务请求,系统在收到请求后需要多久返回结果
吞吐量:在给定的时间能,系统能够处理的数据量


2. ABAP语言的运行原理


首先,先了解下SAP系统基本架构,看一看ABAP程序的运行原理。

SAP自从R/3开始使用三层架构的系统模型,即:

表现层(可通过SAPGUI或浏览器等方式,执行具体的SAP应用程序)
业务逻辑层(ABAP应用程序运行在SAP NetWeaver的ABAP应用服务器上)
数据库访问层(在程序运行过程中,对DB2或HANA等数据库的访问)

在下图的展示中,可以看到,SAP系统也是由最底层文件系统,数据库管理系统,应用服务器、表现层的UI构成。

ABAP语言的执行环境是ABAP应用服务器,其为ABAP程序分配运行所需要内存、工作进程。由此可以看到,ABAP程序的主要用时有两个方面,

一是由程序复杂度决定的work process的运行时间,

另一部分是在运行过程中,对不同位置的数据访问(增、删、改、查)时间。

3. 在哪些方面进行优化?


当访问不同位置的数据时,所需要消耗的时间单位也是不同的。由于硬盘转速的物理极限和数据库的通信连接等原因,访问数据库硬盘的时间消耗要较访问应用服务器内存中的数据,时间花费的要更多。访问各部分的时间消耗关系是:访问数据库 > 访问数据库缓存 > 共享内存/缓存 > 工作进程。

因此,对于ABAP程序的性能优化,可从以下角度介绍使用场景和运用过程中的最佳实践。包括:

如何合理地访问数据库?
如何使用数据库缓存?
如何选用内表?
如何使用batch job?

ABAP性能调优工具的使用等

【01】SAP ABAP性能优化 - 如何减少DB的访问次数?

方法1:尽量使用内表进行数据库的批量操作.

这个原则很好理解,例如,要向数据库中插入100条数据,那么可以通过内表批量操作。

与其使用一般的 loop-endloop 方法来实现向内表添加多条记录,不如使用 append 命令的变体将一个内表的所有记录一次性添加入另一个内表。要注意的是两个内表的结构定义必须完全一样。

* -- Bad -- *
LOOP AT lt_sflight INTO ls_sflight.INSERT INTO sflight VALUES ls_sflight.
ENDLOOP.* -- 推荐使用1-- *
INSERT INTO sflight FROM TABLE lt_sflight.* -- 推荐使用2-- *
Append lines of int_fligh1 to int_fligh2.

修改一个内表的多行纪录
使用modify命令的不同形式加快这种操作的处理速度 

"不建议使用:Loop at int_fligh.If int_fligh-flag is initial.Int_fligh-flag = ‘X’.Endif.Modify int_fligh.Endloop."建议使用:Int_fligh-flag = ‘X’.Modify int_fligh transporting flag where flag is initial.

方法2:使用Join进行在DB层级进行数据的处理

如果通过JOIN能够完成数据的处理,则尽可能减少在ABAP的AS进行处理。

* -- Bad -- *
SELECT carrid connid fldate FROM sflight INTO (xcarrid, xconnid, xfldate) WHERE planetype = '727-200'.SELECT bookid FROM sbook INTO ybookidWHERE carrid = xcarridAND connid = xconnidAND fldate = xfldate.WRITE: / xcarrid, xconnid, ybookid.ENDSELECT.
ENDSELECT.* -- Good-- *
SELECT f~carrid f~connid b~bookidINTO (xcarrid, xconnid, ybookid) FROM sflight AS fINNER JOIN sbook AS bON f~carrid = b~carrid AND f~connid = b~connid AND f~fldate = b~fldateWHERE planetype = '727-200'.WRITE: / xcarrid, xconnid, ybookid.
ENDSELECT.

方法3:使用视图取代基本表,将常用的INNER JOIN创建成DDIC的JOIN VIEW

通过这种方式,在ABAP程序中,可以直接使用VIEW来读取数据多个表的JOIN数据集。

方法4:使用子查询

当需要对同一张表进行多次访问时,可以考虑使用子查询的方式,减少DB的访问次数。

* 举例:确定哪一天的航班预定出座位最多的?* 方式1:双层select。首先选择出预定最多的航班信息,再确定具体的日期。
DATA: ls_sflight TYPE sflight,lv_max     TYPE i.
SELECT carrid connid MAX( seatsocc )FROM sflightINTO (ls_sflight-carrid, ls_sflight-connid, lv_max)GROUP BY carrid connid.SELECT fldate FROM sflightINTO ls_sflight-fldateWHERE carrid = ls_sflight-carridAND connid = ls_sflight-connidAND seatsocc = lv_max.WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.ENDSELECT.ENDSELECT.* 方式2:使用子查询。单层SELECT直接选择出航班信息和日期信息,将最大的座位数在子查询中确定。
SELECT carrid connid fldateFROM sflight AS fINTO (ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate)WHERE seatsocc IN ( SELECT MAX( seatsocc )FROM sflightWHERE carrid = f~carridAND connid = f~connid ).WRITE: / ls_sflight-carrid, ls_sflight-connid, ls_sflight-fldate.
ENDSELECT.

【02】SAP ABAP性能优化 - 如何减少与DB交互的数据量?

为提升程序性能,在ABAP编程过程中应尽量减少DB的访问次数。与此同时,在访问DB时还应尽量减小在与DB交互的数据量,这样可减小DB通信的网络负担,提升访问速度。可通过下面方式达到“减少DB交互数据量”的目标。

方式1: 避免 SELECT *

这一点很好理解,也就是在搜索时,显性指定所需的字段。尽量避免返回不必要的数据,因为任何一个字段的选取,DB都会进行相关的遍历查找,与DB交互时应尽量将数据遍历时间降到最低。

不要图方便使用SELECT * FROM sflight INTO CORRESPONDING FIELD 这样的语句。

方式2:使用WHERE语句限定搜索范围

这一点不做过多解释,合理地使用WHERE语句是任何一种编程语言的通用规范。

方式3:避免在SELECT … ENDSELECT中使用CHECK等类似的判断语句

原因同第二点,合理地通过WHERE限定数据集,仅选取有效的数据进行处理;而非在选取后,再判断数据的有效性。

方式4:使用UP TO n ROWS来限定结果集数目

使用UP TO n ROWS特别适用于选取特定条件、特定数目的SELECT。看下面的例子,从DB中选取10位折扣最大的客户,应直接使用UP TO 10 ROWS, 而非每一次手动计数。

DATA: ls_scustom TYPE scustom,lt_scustom TYPE TABLE OF scustom WITH EMPTY KEY.* -- Bad --*
SELECT id name discountFROM scustomINTO (ls_scustom-id, ls_scustom-name, ls_scustom-discount)WHERE custtype = 'B'ORDER BY discount DESCENDING.IF sy-dbcnt > 10.EXIT.ENDIF.WRITE:/ ls_scustom-id, ls_scustom-name, ls_scustom-discount.
ENDSELECT.* --  Good --*
SELECT id name discountFROM scustom UP TO 10 ROWSINTO CORRESPONDING FIELDS OF TABLE lt_scustomWHERE custtype = 'B'ORDER BY discount DESCENDING.

方式5:在SELECT中使用聚合函数完成运算.

使用ABAP提供的集合函数取代ABAP代码来获得最大或最小值等。

其它可用集合函数还有 min (最小值), avg (平均值), sum (求和) and count (数据选择的行数).

在SELECT中,使用例如COUNT,SUM,MAX等函数完成数据的统计工作,直接返回运算结果。

DATA: lv_seatsocc TYPE sflight-seatsocc,lv_sum      TYPE i VALUE 0.* -- Bad --*
SELECT seatsoccFROM sflight INTO lv_seatsoccWHERE carrid = 'LH'AND fldate LIKE '2018%'.lv_sum = lv_sum + lv_seatsocc.
ENDSELECT.* --  Good --*
SELECT SUM( seatsocc )FROM sflightINTO lv_sumWHERE carrid = 'LH'AND fldate LIKE '2018%'.

方式6:使用UPDATE …SET更新数据库

如果只需要更新DB中某一条数据中的特定几个字段,使用UPDATE … SET无疑是最佳的方式。

DATA: ls_sflight TYPE sflight.
SELECT * FROM sflightINTO ls_sflight UP TO 1 ROWSWHERE carrid = 'LH'.
ENDSELECT.
* option 1 -
ls_sflight-price = ls_sflight-price + 100.
UPDATE sflight FROM ls_sflight.
* option 2 -
ls_sflight-price = ls_sflight-price + 100.
UPDATE sflight SET price = ls_sflight-price
WHERE carrid = ls_sflight-carridAND connid = ls_sflight-connidAND fldate = ls_sflight-fldate.

【03】ABAP性能优化-语法上

ABAP程序基本上都需要从数据库里面抓数,所以性能很重要,同时有一些基本的,和优秀的写法是我们必须要掌握的,不然就会造成程序性能很差。下面给予总结(这里包括有很基本的,也包括有比较少用到的),推荐一个好的SAP标准文档ABAP_PERFORMANCE_DOS_AND_DONTS :

一、基本的几条需要避免的规则(具体的一些怎么替换,可以看三和五):
        1、不使用select....endselect。

        2、基本不使用select *  ,select 需要的字段,数据量大时容易内存溢出dump。

        3、LOOP 里面不用sort  ,在loop外面排序完再进入LOOP。

        4、尽量避免LOOP  里面嵌套select,这样多次访问数据库也会造成性能问题,但是有些时候避免不了也难免。改为外面select,LOOP里面read table。

        5、大数据的read table,使用二分法查找 BINARY SEARCH,用之前要按关键字排序。

READ命令使用顺序查找数据表,这会降低处理速度。取而代之,使用binary search的附加命令,可以使用二分查找算法,可以帮助加快内表查找速度。 在使用binary search之前必须首先将内表排序,否则有可能找不到记录,因为二分查找反复将查找区间对半划分,如果要查找的值小于查找区间的中间位置的数据项值,则查找区间将缩小到前半个区间,否则查找将局限于后半区间。

不推荐使用:Read table int_fligh with key airln = ‘LF’.推荐使用:SORT int_fligh by airln.
Read table int_fligh with key airln = ‘LF’ binary search.

        6、尽量避免LOOP里面嵌套LOOP,特别是当两个内表数据量都很大的时候,如果实在要嵌套LOOP可以参考三和五里面的解决办法。

        7、尽量避免LOOP里面不用delete,append等语句。改成批量处理。

二、index和buffer的合理使用:

1、index的使用,在使用现有的index的时候注意,where条件里面的字段的顺序要跟index一致,而且可以可以适当的去匹配index,创建一些空的字段或者是index后面再加字段,或者是使用index抓出数据后,再去做其它条件的处理。

2、index里面最好只有'=' AND 或者是‘IN’。有其它逻辑条件,会影响index的使用。

3、 如果表是有buffer,可以考虑使用buffer,这样性能也可以有很好的提升,不过首先要去表看看这个是否有buffer:

SELECT SINGLE * FROM T100 INTO T100_WA

BYPASSING BUFFER

WHERE SPRSL = 'D'.

4、使用缓存表。大部分表都有buffer,而且这个我们很难控制,但是我们写出来的语句要尽可能避免“不读buffer”:在 select 命令后面使用 bypass buffer 附加语句可以明确跳过缓存表。推荐使用缓存表因为它可以显著提高程序速度。但是使用以下语句的时候缓存表会被跳过:

  1. Select distinct
  2. Select … for update
  3. Order by, group by, having字段
  4. Joins

5、一般程序到表抓数的时候,会在应用服务层有数据缓存,所以同一个程序,在不同时间先后跑,后面的通常会比较快,因为可以到数据缓存读数。

6、NOT,只能全表扫描,不要用not,换成反面。建议between 换成IN。不建议使用LIKE OR

三、使用一些简单的语句代替复杂的嵌套LOOP:

1、用批量处理的BAPI替换,LOOP 里面call BAPI,例如用BAPI_MATERIAL_SAVEREPLICA 替代 BAPI_MATERIAL_SAVEDATA

2、LOOP 里面delete,可以改成,给内表加一个flag的字段,然后需要删除的打上X,然后用Delete it_1 where delete = ‘X’.

3、LOOP AT 搭INSERT或者是APPEND,可以改成: INSERT SBOOK FROM TABLE itab。 APPEND LINES

4、如果是两个内表都很多数据,但是逻辑要进行嵌套LOOP,可以如下处理,会提升一些性能:

"1.1.1	多层/嵌套LOOP循环性能优化写法
SORT:lt_ztfi0005 BY hcode,lt_prj_prps BY pbukr,lt_prhi     BY up,lt_phs_prps BY pspnr.LOOP AT lt_ztfi0005 INTO ls_ztfi0005.
“ 第一层双层LOOP循环优化READ TABLE lt_prj_prps TRANSPORTING NO FIELDSWITH KEY pbukr = ls_ztfi0005-hcode BINARY SEARCH.IF sy-subrc = 0.lv_cmp_ix = sy-tabix.LOOP AT lt_prj_prps INTO ls_prj_prps FROM lv_cmp_ix.IF ls_prj_prps-pbukr <> ls_ztfi0005-hcode.EXIT.ENDIF.
“ 第二层双层LOOP循环优化READ TABLE lt_prhi TRANSPORTING NO FIELDSWITH KEY up = ls_prj_prps-pspnr BINARY SEARCH.IF sy-subrc = 0.lv_prhi_ix = sy-tabix.LOOP AT lt_prhi INTO ls_prhi FROM lv_prhi_ix.IF ls_prhi-up <> ls_prj_prps-pspnr.EXIT.ENDIF.READ TABLE lt_phs_prps INTO ls_phs_prpsWITH KEY pspnr = ls_prhi-posnr BINARY SEARCH.IF sy-subrc <> 0.CONTINUE.ENDIF.ls_data-cmp_nr = ls_ztfi0005-hcode.ls_data-cmp_nm = ls_ztfi0005-hname.ls_data-prj_nr = ls_prj_prps-posid.ls_data-phs_nm = ls_phs_prps-post1.APPEND ls_data TO et_data.CLEAR ls_data.ENDLOOP.ENDIF.ENDLOOP.ENDIF.ENDLOOP.

5、LOOP 后面用assigning 指针的方式,这样也可以节省空间和时间:可以省去了append,modify等操作,在嵌套LOOP没法像上面那样解决的话,也建议使用指针。

四、有一些标准的FM,如果在LOOP里面使用可以考虑换成使用自己开发,把抓数放出来,然后read(read_text):

1、有很多程序要调用FM read_text,但是当用到LOOP里面调用这个read_text,会比较慢其中到STXH表抓数就会占用很多时间,我们可以考虑对read_text进行优化,把read_text分成两个FM,一个是集中读取STXH,然后另一个是和read_text一样的功能,只是把抓数换成read table。占用性能就会提高很多。

五、一些优秀的良好的ABAP 程序书写习惯:

1、select 数据的时候,如果可以使用join进行内联,尽量2-3个表内联即可。下面这个图可以理解下join的用法:

有时,join太多了,也可以考虑使用创建视图,然后从视图里抓数,例如vbak_kan1。

2、如果要select 数据出来,更改一些字段的值,再进行updata,可以考虑直接使用updata set,省去到表里面抓数:

​
SELECT * FROM sbookINTO xbookWHERE carrid = 'LH'AND connid = '0400' AND fldate >= '20110101'.xbook-connid = '0500'.UPDATE sbook FROM xbook.ENDSELECT.UPDATE sbookSET connid = '0500' WHERE carrid = 'LH' AND connid = '0400' AND fldate >= '20110101'.​

3、读取HASHED表会比其他两种类型更快,同时read table 也可以通过transporting 某些字段到work area,不用全部字段都用上。

4、有些表的数据,是很固定的,例如KNA1或者是T001等,可以抓大部分数据放到内表里,然后去读取,如果读取不到,在抓,不用每次都抓。

5、强制使用索引:(但是如果更改数据库了,就会失效了) %_HINTS DB6 (这个不太建议使用,但是当ST05分析之后,是可以使用某个索引,但系统没有使用,就可以使用这个语句强制使用索引。)

6、及时清空不再使用的大内表释放内存。当一个report在ALV显示完之后,在end-of-selection里面把不用的内表的清空掉,防止有些后台job一次跑两个变量的时候会重复,同时释放内表也是减少内存压力。

7、field-groups的使用,对于多层次的排序和显示非常有用。

8.  使用 “for all entries”, 注意使用前判断内表不为空,否则导致全查询严重影响性能。
在select语句后面的where附加项中可以使用左关联,这会极大的提高程序速度,但同时也有一些局限,如下:
重复项会被从结果数据集中自动删除,因此要注意在select语句中需要给出详细的唯一关键字组合。
如果 For All Entries IN 字段修饰的内表是空表的话,源表的所有行都会被选入目标表中。因此在使用前一定要首先检查第一个表是否为空,这一点很重要,否则会有performance问题。
如果 For All Entries IN 字段修饰的内表很大的话,程序速度反而会减慢,而不是加快。因此应该尽量使该表的数据量控制在一个适当的大小。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

React工程化笔记

脚手架可以帮助我们快速的搭建一个项目结构&#xff0c;在我们之前学习 webpack 的过程中&#xff0c;每次都需要配置 webpack.config.js 文件&#xff0c;用于配置我们项目的相关 loader 、plugin&#xff0c;这些操作比较复杂&#xff0c;但是它的重复性很高&#xff0c;而且…

SQL注入问题

一、什么是sql注入 public class TestSql {public static void main(String[] args) {Scanner inScanner new Scanner(System.in);System.out.println("请输入用户名");String username inScanner.nextLine();System.out.println("请输入密码");String …

安卓笔记1-Retrofit2请求自定义接口

1、整体功能概述 安卓项目中使用Retrofit2实现和自定义接口的网络交互&#xff0c;通过Postman模拟服务端&#xff0c;创建自定义接口。 作用 前后端开发进度对不齐时&#xff0c;客户端可利用本功能模拟测试数据。备忘。 缺点 retrofit模拟接口需要配置响应数据类&#xff…

2024网络准入控制系统排行|好用的网络准入系统有哪些?

随着数字化转型的深化及网络安全威胁的日益复杂&#xff0c;网络准入控制系统&#xff08;NAC&#xff09;已成为企业安全架构中不可或缺的一部分。NAC系统通过对接入网络的设备进行身份验证、安全检测和策略实施&#xff0c;确保仅允许符合安全标准的设备连接至网络&#xff0…

QT上位机绘制一个表格显示MYSQL数据库(六)

一. QT制作MYSQL表格 database.cpp #include "database.h" #include "ui_database.h"#include <QMessageBox> #include <QDebug> #include <QSqlError>database::database(QWidget *parent) :QWidget(parent),ui(new Ui::database) {u…

【ollama】ollama运行GLM4-9B和CodeGeeX4-ALL-9B

一、下载GGUF模型 glm-4-9b-chat-GGUFcodegeex4-all-9b-GGUF 使用modelscope下载 先安装 pip install modelscope 命令1 modelscope download --modelLLM-Research/glm-4-9b-chat-GGUF --local_dir . glm-4-9b-chat.Q5_K.gguf命令2 modelscope download --modelLLM-Researc…

条件匹配工具之ACL概述

基本概念 ACL&#xff0c;即Access Control List&#xff08;访问控制列表&#xff09;&#xff0c;每个ACL但是是由单条或多条Rule&#xff08;规则&#xff09;组成的一个集合 技术背景&#xff1a; 1.用户需求&#xff1a; 用户对网络服务体验的要求越来越高&#xff0c…

学习测试9-接口测试 3-jmeter

jmeter启动 测试计划 1 创建线程组 2 创建http请求 数据类型 from表单数据可以通过剪切板直接粘贴 JSON数据需要从括号开始复制 3 查看结果树 4 http cookie管理器&#xff0c;可以记住登录状态 内部不用设置 5 断言 系统返回的信息进行判断 系统返回“新增会议信息成功” …

python--实验13 异常处理

目录 知识点 异常概述 异常类 异常处理 捕获简单异常 原理 示例 异常处理except 原理及代码格式 try工作原理 标记程序上下文&#xff0c;异常发生时跳转 代码示例 终止行为finally 抛出异常raise 原理 代码格式 示例 自定义异常 原理 示例 断言assert 判…

爱因斯坦:常识就是人到十八岁为止所累积的各种偏见!——早读(逆天打工人爬取热门微信文章解读)

时间过得好快&#xff0c;2023下半年要为了自己的年终终结立下的flag奋斗了&#xff01; 引言Python 代码第一篇 洞见 所有关系的痛苦&#xff0c;都来自“鸡同鸭讲”第二篇结尾 引言 最近应该写的时间会比较晚 因为要看会盘 然后确定一下今天是否有参与的机会 从星期一到现在…

数据预处理在建模中的重要性与常见方法(一):数据清洗篇

一、引言 数据预处理的重要性 数据预处理是数据科学和机器学习中至关重要的一步。高质量的数据预处理可以有效去除噪声、修复缺失值、处理异常值&#xff0c;确保后续分析和模型构建的准确性和可靠性。未经过良好预处理的数据可能导致模型性能下降和错误结论。 数据预处理的…

vue自制表格

一、有时候element-ui的表格不满足需求&#xff0c;需要自定义表格&#xff0c;例如图下 二、上代码 <table class"tablenew table1" cellpadding"0" cellspacing"0"><tr><td>身份证号码</td><td>111111111</…

每日一题,力扣leetcode Hot100之49. 字母异位词分组

该题用哈希表解答&#xff0c;具有统一特征的作为哈希表的键名&#xff0c;然后满足要求的作为值 解法一&#xff1a; 我们将每个字符串进行排序&#xff0c;如果排序后的结果相同&#xff0c;则可以认为是字母异位词&#xff0c;我们将排序后的结果作为哈希表的key&#xff…

java通过jwt生成Token

定义 JWT&#xff08;JSON Web Token&#xff09;简而言之&#xff0c;JWT是一个加密的字符串&#xff0c;JWT传输的信息经过了数字签名&#xff0c;因此传输的信息可以被验证和信任。一般被用来在身份提供者和服务提供者间传递被认证用户的身份信息&#xff0c;以便于从资源服…

[MySQL][内置函数][日期函数][字符串函数][数学函数]详细讲解

目录 1.日期函数1.基础语法2.示例13.示例2 2.字符串函数1.基础语法2.示例 3.数学函数1.基础语法2.示例 4.其他函数 1.日期函数 1.基础语法 日期时间在MYSQL中是区分开的 日期&#xff1a;年月日时间&#xff1a;时分秒 获得年月日select current_date();----------------| cur…

新版网页无插件H.265播放器EasyPlayer.js如何测试demo视频?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff1b;支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#xff0…

【爬虫】滑块缺口识别

滑块示例 分为背景图 和 滑块图 主要目的 识别背景图滑块缺口 下载识别库 pip install opencvcode import numpy as np import cv2def identify_gap(bg, tp):bg1 np.asarray(bytearray(bg), dtypenp.uint8)tp1 np.asarray(bytearray(tp), dtypenp.uint8)# 灰度bg_img cv2…

磁盘分区教程图文

磁盘分区是计算机存储管理中的一项重要操作&#xff0c;它不仅能帮助我们更好地组织和管理数据&#xff0c;还能提高系统的性能和安全性。无论是新手还是有经验的用户&#xff0c;了解和掌握磁盘分区的基本知识都是十分必要的。本篇科普文章旨在为初学者提供一个简单易懂且全面…

汽车免拆诊断案例 | 卡罗拉急加速抖动故障排除

车型信息 2017年改款卡罗拉&#xff0c;排量1.2T&#xff0c;行驶里程48800公里。 故障现象 车辆不管在什么状态下&#xff0c;只要是平缓加速&#xff0c;都不会有抖动。车辆静止时&#xff0c;急加速时&#xff0c;也不会有抖动。但是车速达40公里/小时以上&#xff0c;急加…

sping总览

一、spring体系 1. spring是什么&#xff1f; 轻量级的开源的J2EE框架。它是一个容器框架&#xff0c;主要实现了ioc&#xff0c;同时又通过aop实现了面向切面编程&#xff0c;它又是一个中间层框架&#xff08;万能胶&#xff09;可以起一个连接作用&#xff0c;比如说把myba…