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

【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1

忽然有一天,我想要做一件事:去代码中去验证那些曾经被“灌输”的理论。
                  
                  
                                           – 服装学院的IT男

本篇已收录于Activity短暂的一生系列
欢迎一起学习讨论Android应用开发或者WMS
V:WJB6995
Q:707409815

正文

在这里插入图片描述
生命周期系列:

  • Activity生命周期之onPause

  • onCreate,onStart,onResume-1

  • onCreate,onStart,onResume-2

  • Activity生命周期之onStop-1

  • Activity生命周期之onStop-2

  • Activity生命周期之onDestory

在整个启动流程中,上一篇介绍了第一阶段:SourceActivity 的 onPause

现在分析第二阶段:TargetActivity 启动后会依次执行 onCreate,onStart,onResume。

另外还会完整的介绍一下 Activity 生命周期的事务是如何触发的。

1. 启动流程介绍

我们知道 onCreate 这个生命周期表示 Activity 的创建,对应 LaunchActivityItem 这个事务,源码中构建这个事务唯一的地方就在 ActivityTaskSupervisor::realStartActivityLocked 方法。

而 ActivityTaskSupervisor::realStartActivityLocked 方法的执行逻辑,在[Activity启动流程系列]说过要启动 TargetActivity 有2个必要条件:

    1. TargetActivity 所在的应用进程已经启动
    1. SourceActivity 需要执行 onPause

不考虑异常情况,能执行 onCreate 的场景就是冷热启动了,冷热启动区别也就在于多了个需要创建应用进程,不过最终都会执行到 ActivityTaskSupervisor::realStartActivityLocked 方法。

无论是启动进程后执行过来的,还是上篇提到的 SourceActivity 执行 activityPaused 流程触发过来的结果都是一样的,不必太在意

开始撸代码

# ActivityTaskSupervisor boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {// 1. 判断是否执行完了pause 。 也就是2个条件之一,必须要执行完pause才可以进入后面if (!mRootWindowContainer.allPausedActivitiesComplete()) {// While there are activities pausing we skipping starting any new activities until// pauses are complete. NOTE: that we also do this for activities that are starting in// the paused state because they will first be resumed then paused on the client side.// 不满足添加就打logProtoLog.v(WM_DEBUG_STATES,"realStartActivityLocked: Skipping start of r=%s some activities pausing...",r);return false;}......// 2. wm_restart_activity EventLogTags.writeWmRestartActivity(r.mUserId, System.identityHashCode(r),task.mTaskId, r.shortComponentName);// 3.重点* 创建Activity启动事务.将构建的 LaunchActivityItem 添加到 clientTransaction 中final ClientTransaction clientTransaction = ClientTransaction.obtain(proc.getThread(), r.token);......clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.getFilteredReferrer(r.launchedFromPackage), task.voiceInteractor,proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),results, newIntents, r.takeOptions(), isTransitionForward,proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));final ActivityLifecycleItem lifecycleItem;if (andResume) {// 4.重点*. 设置预期的最终状态Resume逻辑,启动走的这。 表示需要执行到onCreatelifecycleItem = ResumeActivityItem.obtain(isTransitionForward);} else {//  Pause 逻辑lifecycleItem = PauseActivityItem.obtain();}clientTransaction.setLifecycleStateRequest(lifecycleItem);// 5.重点* 调度事务,将clientTransaction添加到生命周期管理器中mService.getLifecycleManager().scheduleTransaction(clientTransaction);}
    1. 如果有Activity没有执行完 pause ,则不能执行新的Activity的启动。 如果不满足条件也会相应的ProtoLog
    1. 打印Events日志,格式为:wm_restart_activity: [0,253598020,21,com.google.android.dialer/.extensions.GoogleDialtactsActivity]
    1. 构建 LaunchActivityItem 事务,将会触发创建Activity,并执行到 onCreate
    1. 构建 ResumeActivityItem 事务,将会触发执行到Activity的 onResume
    1. 执行事务

后面的流程其实可以直接去看应用端这2个事务的执行,不过我对这中间的调用比较好奇,所以把生命周期跨进程调用事务的逻辑也梳理了一遍。对这块比较了解的可以跳过,直接看第三章生命周期相关的内容

2. Activity 生命周期事务跨进程处理方式详解

2.1 了解ClientTransaction

在 ActivityTaskSupervisor::realStartActivityLocked 方法中对跨进程执行生命周期事务的代码可以归纳为以下几步:

    1. 构建出 ClientTransaction
    1. 构建 onCreate 和 onResume对应的2个事务,并保存到 ClientTransaction 中
    1. 通过 ClientLifecycleManager::scheduleTransaction 方法来触发事务的调度执行,唯一参数就是 ClientTransaction

这一小节先来了解一下这个 ClientTransaction 到底是什么

# ClientTransaction// 实现Parcelable接口,说明可序列化public class ClientTransaction implements Parcelable, ObjectPoolItem {// 几个重要的成员变量private List<ClientTransactionItem> mActivityCallbacks;private ActivityLifecycleItem mLifecycleStateRequest;// 目标进程private IApplicationThread mClient;// 目标Activityprivate IBinder mActivityToken;// client :对应进程// activityToken :创建ActivityRecord时的匿名tokenpublic static ClientTransaction obtain(IApplicationThread client, IBinder activityToken) {ClientTransaction instance = ObjectPool.obtain(ClientTransaction.class);if (instance == null) {instance = new ClientTransaction();}instance.mClient = client;instance.mActivityToken = activityToken;return instance;}// 拿到对应public IBinder getActivityToken() {return mActivityToken;}public void addCallback(ClientTransactionItem activityCallback) {if (mActivityCallbacks == null) {mActivityCallbacks = new ArrayList<>();}// 事务添加到 mActivityCallbacks 列表中mActivityCallbacks.add(activityCallback);}// 事务赋值给 mLifecycleStateRequest 变量public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {mLifecycleStateRequest = stateRequest;}// 目标进程执行事务public void schedule() throws RemoteException {mClient.scheduleTransaction(this);}}

ClientTransaction 的核心方法就这些,结合 ActivityTaskSupervisor::realStartActivityLocked 方法的使用得出以下结论:

    1. ClientTransaction::obtain 构建出一个 ClientTransaction 对象,2个参数分别为目标进程,和目标Activity
    1. addCallback 方法会将 LaunchActivityItem 放到 内部的 mActivityCallbacks 列表中
    1. setLifecycleStateRequest 方法将 ResumeActivityItem 事务赋值给了 mLifecycleStateRequest 变量。

这里还有个重要的方法 schedule() ,最终会触发目标进程执行当前这个 ClientTransaction 。

2.2 事务的调度执行

上一小节知道生命周期的事务都被包装在了一个 ClientTransaction 对象中,现在来看看 ClientLifecycleManager::scheduleTransaction 方法是如何触发对应事务执行的。

该方法有多个重载,但是本质都一样


# ClientLifecycleManagervoid scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();// 重点* 调用ClientTransaction::scheduletransaction.schedule();......}void scheduleTransaction(@NonNull IApplicationThread client, @NonNull IBinder activityToken,@NonNull ActivityLifecycleItem stateRequest) throws RemoteException {//  构建 一个 ClientTransaction,调用上面的scheduleTransactionfinal ClientTransaction clientTransaction = transactionWithState(client, activityToken,stateRequest);scheduleTransaction(clientTransaction);}......忽略另外几个重载, 都是内部构建出一个 ClientTransaction 

主要就是执行了 ClientTransaction::schedule 方法。

2.3 应用进程处理

ClientTransaction::schedule 方法会跨进程调用到目标进程的 scheduleTransaction 方法,我们知道进程指的就是 ActivityThread 内部类 ApplicationThread

# ActivityThread$ApplicationThread@Overridepublic void scheduleTransaction(ClientTransaction transaction) throws RemoteException {// 这里调用的是ActivityThread的父类 ClientTransactionHandlerActivityThread.this.scheduleTransaction(transaction);}# ClientTransactionHandlervoid scheduleTransaction(ClientTransaction transaction) {// 执行 preExecute (预执行)transaction.preExecute(this);// 重点* 发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}

先执行 preExecute 方法,最重要的是执行发送了一个 EXECUTE_TRANSACTION 消息,并把 ClientTransaction 传过去了。

这个消息的处理在 ActivityThread 中。

# ActivityThreadprivate final TransactionExecutor mTransactionExecutor = new TransactionExecutor(this);class H extends Handler {public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {......case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;// 处理mTransactionExecutor.execute(transaction);......break;......}}}

ClientTransaction 又被传递到 TransactionExecutor 中处理了。

# TransactionExecutorpublic void execute(ClientTransaction transaction) {......// LaunchActivityItemexecuteCallbacks(transaction);// ResumeActivityItemexecuteLifecycleState(transaction);......}

2.3.1 executeCallbacks 和 executeLifecycleState 方法

为什么我在上面注释里说 executeCallbacks 是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem 呢?
代码中有答案:

# TransactionExecutorpublic void executeCallbacks(ClientTransaction transaction) {// 获取 callback 的元素,没有就返回final List<ClientTransactionItem> callbacks = transaction.getCallbacks();if (callbacks == null || callbacks.isEmpty()) {// No callbacks to execute, return early.return;}......// 当前场景是触发 LaunchActivityItem的execute方法item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);......}private void executeLifecycleState(ClientTransaction transaction) {// 获取tLifecycleStateRequest,没有就返回final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();if (lifecycleItem == null) {// No lifecycle request, return early.return;}......// 重点* 将Activity的状态转换至接近最终目标状态的位置  也就是会触发onStartcycleToPath(r, lifecycleItem.getTargetState(), true /* excludeLastState */, transaction);// Execute the final transition with proper parameters.// 当前场景是触发LaunchActivityItem的executelifecycleItem.execute(mTransactionHandler, token, mPendingActions);lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);}

而之前SystemService对这2个事务的处理如下:

ActivityTaskSupervisor::realStartActivityLockedLaunchActivityItem.obtain   -- 添加到事务到 mActivityCallbacks 列表ResumeActivityItem.obtain   -- 设置事务到 mLifecycleStateRequestClientLifecycleManager::scheduleTransaction  -- 触发事务的执行

所以说:executeCallbacks 方法是处理 LaunchActivityItem,executeLifecycleState 是处理 ResumeActivityItem。

2.4 小结

经过上面这些分析,我们知道在 ActivityTaskSupervisor::realStartActivityLocked 方法中启动 Activity 就是构建了2个事务到 ClientTransaction 中,并跨进程到目标进程执行。

2个事务从SystemService进程到目标应用进程完整的调用链如下:

ActivityTaskSupervisor::realStartActivityLockedClientTransaction::obtain             -- 构建客户端事务LaunchActivityItem::obtain            -- 构建 onCreate 启动事务ClientTransaction::addCallback        -- onCreate事务添加进回调ResumeActivityItem::obtain            -- 构建 onResume 事务ClientTransaction::setLifecycleStateRequest  --  onResume 事务添加进LifecycleStateRequestClientLifecycleManager::scheduleTransaction  -- 执行事务ClientTransaction::schedule               -- 触发目标进程执行ActivityThread$ApplicationThread::scheduleTransaction  -- 进入应用进程ClientTransactionHandler::scheduleTransactionClientTransaction::preExecuteActivityThread::sendMessage                     -- 发送“EXECUTE_TRANSACTION”消息ActivityThread$H::handleMessage TransactionExecutor::executeTransactionExecutor::executeCallbacks        -- LaunchActivityItem 事务LaunchActivityItem::execute              -- 触发 onCreateLaunchActivityItem::postExecuteTransactionExecutor::executeLifecycleState   -- ResumeActivityItem 事务TransactionExecutor::cycleToPath         -- 触发 onStartResumeActivityItem::execute              -- 触发 onResumeResumeActivityItem::postExecute

时序图如下:
在这里插入图片描述
可以看到从 生命周期事务的执行到真正触发其 execute 方法,中间的调用链还是很长的,不过这个流程也不算很重要,一般看到 ResumeActivityItem 这种事务构建了,直接去看对应的 execute,postExecute 等方法就好了。

从调用链上也看到了 3个生命周期的执行顺序和期望的log打印也是一样的,当然具体是怎么执行到的要看后续代码分析。

3. 总结

这一篇对介绍了 Activity 启动流程中 SystemService 端末尾的工作,
另外介绍了一下 Activity 生命周期事务跨进程处理方式,关于onCreate,onStart,onResume 这3个生命周期在SystemService 端的流程介绍完了,下一篇是重点,会详细介绍在应用端对这3个生命周期的处理流程。

相关文章:

【Android 13源码分析】Activity生命周期之onCreate,onStart,onResume-1

忽然有一天&#xff0c;我想要做一件事&#xff1a;去代码中去验证那些曾经被“灌输”的理论。                                                                                  – 服装…...

达梦数据库开启归档模式

目录 一、什么是归档模式&#xff1f; 二、开启归档模式的步骤 1、创建归档目录 2、进入dm数据库bin目录 3、登录数据库 4、关闭数据库 5、启动数据库到Mount状态 6、增加本地归档日志文件 7、开启归档 8、启动数据库 9、验证是否开启成功 三、开启归档模式的优…...

C++ 语言特性07 - 静态成员的初始化

一&#xff1a;概述 1. 静态成员变量通常在类定义内部声明&#xff0c;并在类定义外部定义和初始化。 class MyClass { public:static int staticVar; // 声明 };int MyClass::staticVar 42; // 定义和初始化 2. 从C11开始&#xff0c;可以在类内直接初始化静态数据成员&am…...

【数据结构】图论基础

文章目录 图的概念图的基本概念图的类型图的表示方法 图的相关基本概念1. 路径&#xff08;Path&#xff09;2. 连通性&#xff08;Connectivity&#xff09;3. 图的度&#xff08;Degree&#xff09;4. 子图&#xff08;Subgraph&#xff09;5. 生成树&#xff08;Spanning Tr…...

HTML5实现好看的唐朝服饰网站模板源码2

文章目录 1.设计来源1.1 网站首页1.2 唐装演变1.3 唐装配色1.4 唐装花纹1.5 唐装文化 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.ne…...

golang web笔记-2.请求request

什么是request http消息分为request&#xff08;请求&#xff09; 和 response&#xff08;响应&#xff09; request&#xff1a;在go中是一个struct&#xff0c;代表了客户段发送的http请求&#xff0c;已可以通过request 的方法访问请求中的cookie、URL、User Agent&#xf…...

docker的安装与启动——配置国内Docker源

移除旧版本docker sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 配置docker yum源。 sudo yum install -y yum-utils sudo yum-config-manager –add-repo ht…...

httpsok-v1.17.0-SSL通配符证书自动续签

&#x1f525;httpsok-v1.17.0-SSL通配符证书自动续签 介绍 httpsok 是一个便捷的 HTTPS 证书自动续签工具&#xff0c;基于全新的设计理念&#xff0c;专为 Nginx 、OpenResty 服务器设计。已服务众多中小企业&#xff0c;稳定、安全、可靠。 一行命令&#xff0c;一分钟轻…...

相机、镜头参数详解以及相关计算公式

一、工业相机参数 1、分辨率 相机每次采集图像的像素点数&#xff0c;也是指这个相机总共有多少个感光晶片。在采集图像时&#xff0c;相机的分辨率对检测精度有很大的影响&#xff0c;在对同样打的视场成像时&#xff0c;分辨率越高&#xff0c;对细节的展示越明显。 相机像素…...

【微服务】组件、基础工程构建(day2)

组件 服务注册和发现 微服务模块中&#xff0c;一般是以集群的方式进行部署的&#xff0c;如果我们调用的时候以硬编码的方式&#xff0c;那么当服务出现问题、服务扩缩容等就需要对代码进行修改&#xff0c;这是非常不好的。所以微服务模块中就出现了服务注册和发现组件&…...

ESP32微信小程序SmartConfig配网

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ESP32&微信小程序SmartConfig配网 前言一、SmartConfig是什么&#xff1f;二、使用乐鑫官方的smart_config例子1.运行照片 三、微信小程序总结 前言 本人是酷爱ESP32S3这…...

【PostgreSQL】提高篇——深入了解不同类型的 JOIN(INNER JOIN、LEFT JOIN、RIGHT JOIN、FULL JOIN)应用操作

1. JOIN 的基础概念 在 SQL 中&#xff0c;JOIN 是用于从两个或多个表中组合行的操作。JOIN 允许我们根据某些条件将表中的数据关联在一起。常见的 JOIN 类型包括&#xff1a; INNER JOIN&#xff1a;仅返回两个表中满足连接条件的行。LEFT JOIN&#xff08;或 LEFT OUTER JO…...

师生健康信息管理:SpringBoot技术突破

第4章 系统设计 4.1 系统体系结构 师生健康信息管理系统的结构图4-1所示&#xff1a; 图4-1 系统结构 登录系统结构图&#xff0c;如图4-2所示&#xff1a; 图4-2 登录结构图 师生健康信息管理系统结构图&#xff0c;如图4-3所示。 图4-3 师生健康信息管理系统结构图 4.2…...

【完-网络安全】Windows注册表

文章目录 注册表启动项及常见作用五个根节点常见入侵方式 注册表 注册表在windows系统的配置和控制方面扮演了一个非常关键的角色&#xff0c;它既是系统全局设置的存储仓库&#xff0c;也是每个用户的设置信息的存储仓库。 启动项及常见作用 快捷键 WinR打开运行窗口&#x…...

车辆重识别(2021NIPS在图像合成方面,扩散模型打败了gans网络)论文阅读2024/10/01

本文在架构方面的创新&#xff1a; ①增加注意头数量&#xff1a; 使用32⇥32、16⇥16和8⇥8分辨率的注意力&#xff0c;而不是只使用16⇥16 ②使用BigGAN残差块 使用Big GAN残差块对激活进行上采样和下采样 ③自适应组归一化层 将经过组归一化操作后的时间步和类嵌入到每…...

掌控物体运动艺术:图扑 Easing 函数实践应用

现如今&#xff0c;前端开发除了构建功能性的网站和应用程序外&#xff0c;还需要创建具有吸引力且尤为流畅交互的用户界面&#xff0c;其中动画技术在其中发挥着至关重要的作用。在数字孪生领域&#xff0c;动画的应用显得尤为重要。数字孪生技术通过精确模拟现实世界中的对象…...

Python从入门到高手4.2节-掌握循环控制语句

目录 4.2.1 理解循环控制 4.2.2 for循环结构 4.2.3 循环结构的else语句 4.2.4 while循环结构 4.2.5 循环结构可以嵌套 4.2.6 国庆节吃好玩好 4.2.1 理解循环控制 我们先来搞清楚循环的含义。以下内容引自汉语词典: 循环意指往复回旋&#xff0c;指事物周而复始地运动或变…...

CSS 中的overscroll-behavior属性

overscroll-behavior 是 CSS 中的一个属性&#xff0c;它用于控制元素在发生滚动时&#xff0c;当滚动范围超出其边界时的行为。这个属性对于改善用户体验特别有用&#xff0c;尤其是在移动端设备上&#xff0c;当用户尝试滚动一个已经达到滚动极限的元素时&#xff0c;可以通过…...

GPT对话知识库——在STM32的平台下,通过SPI读取和写入Flash的步骤。

目录 1&#xff0c;问&#xff1a; 1&#xff0c;答&#xff1a; 步骤概述 步骤 1&#xff1a;SPI 初始化 步骤 2&#xff1a;Flash 初始化&#xff08;可选&#xff09; 步骤 3&#xff1a;发送读取命令 示例&#xff1a;发送读取数据命令 步骤 4&#xff1a;读取数据…...

Pytorch基本知识

model.state_dict()、model.parameters()和model.named_parameters()的区别 parameters()只包含模块的参数,即weight和bias(包括BN的)。 named_parameters()返回包含模块名和模块的参数的列表,列表的每个元素均是包含layer name和layer param的元组。layer param就是param…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)

本文把滑坡位移序列拆开、筛优质因子&#xff0c;再用 CNN-BiLSTM-Attention 来动态预测每个子序列&#xff0c;最后重构出总位移&#xff0c;预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵&#xff08;S…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释

以Module Federation 插件详为例&#xff0c;Webpack.config.js它可能的配置和含义如下&#xff1a; 前言 Module Federation 的Webpack.config.js核心配置包括&#xff1a; name filename&#xff08;定义应用标识&#xff09; remotes&#xff08;引用远程模块&#xff0…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解

进来是需要留言的&#xff0c;先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码&#xff0c;输入的<>当成字符串处理回显到页面中&#xff0c;看来只是把用户输…...