Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成logback 及 原理分析
文章目录
- Pre
- 官网
- 集成步骤
- POM依赖
- 使用
- 第一步:编写 Logback 的配置文件
- 第二步:在代码中使用 SLF4J
- 原理分析
- 1. 获取对应的 `ILoggerFactory`
- 2. 根据 `ILoggerFactory` 获取 `Logger` 实例
- 3. 日志记录过程
- 小结
Pre
Java - 日志体系_Apache Commons Logging(JCL)日志接口库
Java - 日志体系_Apache Commons Logging(JCL)日志接口库_适配Log4j2 及 源码分析
Java - 日志体系_Apache Commons Logging(JCL)日志接口库_桥接Logback 及 源码分析
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J实现原理分析
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成JUL 及 原理分析
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成Log4j1.x 及 原理分析
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成Log4j2.x 及 原理分析
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成logback 及 原理分析
官网
https://slf4j.org/
Simple Logging Facade for Java (SLF4J) 用作各种日志记录框架(e.g. java.util.logging、logback、log4j)的简单外观或抽象,允许最终用户在部署时插入所需的日志记录框架 时间。
请注意,启用 SLF4J 的库意味着仅添加一个强制依赖项,即 slf4j-api.jar。 如果在类路径上找不到绑定/提供程序,则 SLF4J 将 default 为 no-operation 实现。
SLF4J user manual:https://slf4j.org/manual.html
集成步骤
POM依赖
<!-- slf4j-api --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>2.0.16</version></dependency><!-- logback --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.5.15</version></dependency><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.5.15</version></dependency>
slf4j-api
: SLF4J 的核心 API,用于定义日志接口。logback-core
和logback-classic
: Logback 的核心和经典模块,提供日志记录功能,并与 SLF4J 集成。
使用
第一步:编写 Logback 的配置文件
创建一个 logback.xml
配置文件,设置 Logback 的日志级别和输出格式。
<configuration><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} ===>>>>>> %msg%n</pattern></encoder></appender><!-- 文件输出 --><appender name="FILE" class="ch.qos.logback.core.FileAppender"><file>application.log</file><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 可选:配置日志文件滚动 --><appender name="ROLLING_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"><file>application.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!-- 按天滚动日志文件 --><fileNamePattern>application-%d{yyyy-MM-dd}.log</fileNamePattern><!-- 最多保留 30 天的日志文件 --><maxHistory>30</maxHistory></rollingPolicy><encoder><pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern></encoder></appender><!-- 根日志记录器 --><root level="debug"><appender-ref ref="STDOUT" /><appender-ref ref="ROLLING_FILE" /></root><!-- 可选:配置特定包的日志级别 --><logger name="com.artisan" level="info" />
</configuration>
第二步:在代码中使用 SLF4J
在代码中通过 LoggerFactory.getLogger()
获取日志记录器实例,并使用 SLF4J API 记录日志。
package com.artisan;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** Slf4jLogback**/
public class Slf4jLogback {private static final Logger logger= LoggerFactory.getLogger(Slf4jLogback.class);public static void main(String[] args){logger.trace("Slf4jLogback This is a trace message");logger.debug("Slf4jLogback This is a debug message");logger.info("Slf4jLogback This is an info message");logger.warn("Slf4jLogback This is a warning message");logger.error("Slf4jLogback This is an error message");}}
原理分析
1. 获取对应的 ILoggerFactory
Logback 与 SLF4J 的集成通过 StaticLoggerBinder
类完成。StaticLoggerBinder
是 Logback 提供的一个实现,用于将 SLF4J 的日志接口与 Logback 的日志实现绑定。
- 步骤 1.1:SLF4J 通过类加载器加载
org/slf4j/impl/StaticLoggerBinder.class
类,找到了logback-classic
包中的绑定类。 - 步骤 1.2:
StaticLoggerBinder
创建并返回ILoggerFactory
实例。Logback 使用LoggerContext
作为ILoggerFactory
的实现类。
StaticLoggerBinder.getSingleton().getLoggerFactory(); // 获取 LoggerContext 实例
在 LoggerContext
中,Logback 初始化时会加载并解析配置文件(如 logback.xml
)。这确保了日志配置在应用启动时就已准备好。
2. 根据 ILoggerFactory
获取 Logger
实例
LoggerContext
是 Logback 中用于管理日志的核心对象,它实现了 SLF4J 的 ILoggerFactory
接口。通过 LoggerContext
,SLF4J 会获得实际的 Logger
实例。
LoggerContext
会根据日志名称返回一个ch.qos.logback.classic.Logger
实例,这个 Logger 类实现了 SLF4J 的Logger
接口。
Logger logger = loggerContext.getLogger(name); // 获取 Logback 的 Logger 实例
-
步骤 2.1:当 SLF4J 调用
LoggerFactory.getLogger()
时,它会通过LoggerContext
获取对应的Logger
实例,这个实例是 Logback 自定义的Logger
,但它实现了 SLF4J 的Logger
接口。 -
步骤 2.2:
ch.qos.logback.classic.Logger
实现了 SLF4J 定义的Logger
接口,因此可以通过 SLF4J 的 API 记录日志,并将日志委托给 Logback 来处理。
3. 日志记录过程
当调用 SLF4J 的日志方法时(如 logger.debug()
),日志请求会被转发到 Logback 中的 Logger
实例,该实例最终会根据 logback.xml
配置输出日志。Logback 的 Logger
实现会委托给 Appender
(如 ConsoleAppender
)来完成日志输出。
- 日志输出的格式由
logback.xml
中定义的PatternLayout
决定。 - Logback 会根据日志级别(如
DEBUG
、INFO
)和配置的Appender
进行输出。
小结
- 依赖关系:通过
slf4j-api
、logback-core
和logback-classic
实现 SLF4J 与 Logback 的集成。 - 核心过程:SLF4J 通过
StaticLoggerBinder
类绑定到 Logback,LoggerContext
返回 Logback 的Logger
实例。 - 日志调用转发:SLF4J 的日志调用会被转发到 Logback 的
Logger
实例,并根据logback.xml
配置进行日志输出。
相关文章:
Java - 日志体系_Simple Logging Facade for Java (SLF4J)日志门面_SLF4J集成logback 及 原理分析
文章目录 Pre官网集成步骤POM依赖使用第一步:编写 Logback 的配置文件第二步:在代码中使用 SLF4J 原理分析1. 获取对应的 ILoggerFactory2. 根据 ILoggerFactory 获取 Logger 实例3. 日志记录过程 小结 Pre Java - 日志体系_Apache Commons Logging&…...
机器学习-方案设计题(在线医疗诊断项目)
在一个在线医疗诊断项目中,我们希望利用机器学习算法来预测患者是否患有某种疾病。请设计一个方案,包括数据收集、预处理、特征选择、模型选择和评估等步骤来完成这个任务。 1.数据收集数据来源 电子病历系统:收集患者的基本信息&…...
基于Sentinel的服务保护方案的三种方式(请求限流、线程隔离、服务熔断)超详细讲解
目录 1、三种方式介绍 1.1请求限流 1.2 线程隔离方案 1.3 服务熔断 2、基于sentinel实现 2.1 启动sentinel 2.2 基于springboot整合sentinel 2.2.1请求限流 2.2.2请求隔离 2.2.2.1 OpenFeign整合Sentinel 2.2.3 服务熔断 2.2.3.1 编写降级代码 2.2.3.2 服务熔断 1、…...
[开源]C++代码分享
一,声明 被人水平有限,开源只是为了分享。勿喷!!!还请大佬指点。 二,代码 // --------------------------------------------------------- 头文件 ----------------------------------------------- #in…...
vulnhub ica1
搭建靶机跟之前一样 不过这个要修改一下网卡;下面链接有教程 vulnhub jangow靶机-CSDN博客 1.扫描靶机IP arp-scan -l 192.168.47.135 2.信息收集 nmap -sS 192.168.47.135 访问网站 这个是一个web应用,框架是qdpm 9.2 在kali上搜索一下发现有两个漏洞&#x…...
Linux(Centos 7.6)基础命令/常用命令说明
1.目录相关命令 命令命令说明pwd用于显示/打印当前目录位置。ls/ll 列出当前目录下的文件或者目录,ll是ls -l的别名,ls仅显示名称,ll会显示详细的目录文件信息。 cd目录切换,常见用法有,cd /切换到根目录,…...
Solon 加入 GitCode:助力国产 Java 应用开发新飞跃
在当今数字化快速发展的时代,Java 应用开发框架不断演进,开发者们始终在寻找更快、更小、更简单的解决方案。近期,Solon 正式加入 GitCode,为广大 Java 开发者带来全新的开发体验,尤其是在国产应用开发进程中ÿ…...
Browser Use:AI智能体自动化操作浏览器的开源工具
Browser Use:AI智能体自动化操作浏览器的开源工具 Browser Use 简介1. 安装所需依赖2. 生成openai密钥3. 编写代码4. 运行代码5. 部署与优化5.1 部署AI代理5.2 优化与扩展总结Browser Use 简介 browser-use是一个Python库,它能够帮助我们将AI代理与浏览器自动化操作结合起来;…...
ArcGIS中怎么进行水文分析?(思路介绍)
最近有人咨询,ArcGIS中怎么进行水文分析,大致的说一下河网提取的思路哈 解决思路:dem填洼→计算水流方向→计算水流累积矩阵→形成河网 dem填洼 计算水流方向 计算水流累积矩阵 用栅格计算器,设阈值(自己多次尝试&…...
2024年中国新能源汽车用车发展怎么样 PaperGPT(一)
概述 在国家政策的强力扶持下,2024年中国新能源汽车市场迎来了新的发展机遇。本文将基于《中国新能源汽车用车报告(2024年)》的数据,对新能源汽车的市场发展和用车趋势概述。 新能源汽车市场发展 政策推动:国家和地…...
KubeOS
title: 探秘 KubeOS:云原生操作系统的创新先锋 date: ‘2024-12-31’ category: blog tags: KubeOS云原生操作系统容器编排 sig: CloudNative archives: ‘2024-12’ author:way_back summary: KubeOS 作为一款专为云原生应用打造的操作系统,深度集成了…...
html文件通过script标签引入外部js文件,但没正确加载的原因
移动端H5应用,html文件通过script标签引入外部js文件,但没正确加载,在移动设备上难以排查。通过PC浏览器打开,发现js被阻止了:blocked:mixed-content。 原因在于: “blocked:mixed - content” 是浏览器的…...
[创业之路-225]:《华为闭环战略管理》-4-华为的商业智慧:在价值链中探索取舍之道与企业边界
目录 一、在价值链中探索取舍之道与企业边界 价值链的深刻洞察 取舍之道:有所为,有所不为 垂直整合与横向整合的平衡 企业边界与活动边界的界定 采购与外包的智慧运用 结语 二、企业外部价值流:上游、中游、下游、终端 上游…...
让 Agent 具备语音交互能力:技术突破与应用前景(16/30)
让 Agent 具备语音交互能力:技术突破与应用前景 一、引言 在当今数字化时代,人机交互方式正经历着深刻的变革。从早期的命令行界面到图形用户界面,再到如今日益普及的语音交互,人们对于与机器沟通的便捷性和自然性有了更高的追求…...
代理IP助力VR行业革新,小派科技引领技术潮流
随着VR行业的新一轮技术升级,更高分辨率、更宽视场角以及更舒适的佩戴体验已成为各大厂商竞争的核心。在这一浪潮中,小派科技凭借其最新发布的视网膜级VR头显——Crystal Super,成功吸引了市场的目光。而在这场技术革新的背后,代理…...
C#Halcon图像处理畸变校正之曲面校正
图像校正场景一般有两种,其一由镜头本身或安装角度引起,其二是被拍摄物品本身引起 理论处理流程 我的处理处理流程 1,加载网格校正图像 2,确定符合条件的网格区域 3,显示网格鞍点 4,显示网格线 5ÿ…...
JSON结构快捷转XML结构API集成指南
JSON结构快捷转XML结构API集成指南 引言 在当今的软件开发世界中,数据交换格式的选择对于系统的互操作性和效率至关重要。JSON(JavaScript Object Notation)和XML(eXtensible Markup Language)是两种广泛使用的数据表…...
Coroutine 基础四 —— CoroutineScope 与 CoroutineContext
1、定位 CoroutineContext,协程上下文。协程用到的所有信息都属于协程上下文,根据功能不同,划分成了不同的分类。管理流程用的是 Job,管理线程用的是 ContinuationInterceptor,等等。 CoroutineScope 的定位有两点&a…...
科技云报到:洞见2025年科技潮流,技术大融合开启“智算时代”
科技云报到原创。 随着2024年逐渐接近尾声,人们不禁开始展望即将到来的2025年。这一年,被众多科技界人士视为开启新纪元的关键节点。站在新的起点上,我们将亲眼目睹未来科技如何改变我们的世界。从人工智能到量子计算,从基因编辑…...
MySQL有哪些锁?
1.MySQL有哪些锁? 全局锁表级锁 表锁元数据锁意向锁 行级锁 记录锁间隙锁临键锁临时意向锁 我了解的是MySQL的锁可以分为全局锁、表级锁、行级锁。 我比较熟悉的是表级锁和行级锁,如果我们对表结构进行修改时,MySQL就会对这个表结构加一个…...
通过交叉实现数据触底分页效果new IntersectionObserver()(html、react、vue2、vue3)中使用
react中用法 import React, { useState, useEffect, useRef } from react;const InfiniteScroll () > {const [items, setItems] useState([]);const [loading, setLoading] useState(false);const [page, setPage] useState(1);const loaderRef useRef(null);// 模拟…...
DeepSeek-V3-Base 模型技术解析
DeepSeek-V3-Base 模型技术解析 目录 引言DeepSeek-V3-Base 模型概述模型架构 3.1 Transformer 基础3.2 DeepSeek-V3-Base 的改进 训练过程 4.1 数据预处理4.2 训练策略4.3 优化器与学习率调度 模型性能评估 5.1 基准测试5.2 实际应用案例 模型优化与调参 6.1 超参数调优6.2 …...
Qt5 中 QGroupBox 标题下沉问题解决
我们设置了QGroupBox 样式之后,发现标题下沉了,那么如何解决呢? QGroupBox {font: 12pt "微软雅黑";color:white;border:1px solid white;border-radius:6px; } 解决后的效果 下面是解决方法: QGroupBox {font: 12pt "微软雅黑";color:white;bo…...
Linux Debian安装ClamAV和命令行扫描病毒方法,以及用Linux Shell编写了一个批量扫描病毒的脚本
ClamAV是一个开源的跨平台病毒扫描引擎,用于检测恶意软件、病毒、木马等安全威胁。 一、Linux Debian安装ClamAV 在Linux Debian系统上安装ClamAV,你可以按照以下步骤进行: 更新软件包列表: 打开终端并更新你的软件包列表&#…...
数据结构与算法之动态规划: LeetCode 53. 最大子数组和 (Ts版)
最大子数组和 https://leetcode.cn/problems/maximum-subarray/description/ 描述 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和子数组是数组中的一个连续部分 示例 1 …...
活动预告 | Microsoft Azure 在线技术公开课:使用 Azure OpenAI 服务构建生成式应用
课程介绍 通过 Microsoft Learn 免费参加 Microsoft Azure 在线技术公开课,掌握创造新机遇所需的技能,加快对 Microsoft Cloud 技术的了解。参加我们举办的“使用 Azure OpenAI 服务构建生成式应用”活动,了解如何使用包括 GPT 在内的强大的…...
Python爬虫(二)- Requests 高级使用教程
文章目录 前言一、Session 对象1. 简介2. 跨请求保持 Cookie3. 设置缺省数据4. 方法级别参数不被跨请求保持5. 会话作为上下文管理器6. 移除字典参数中的值 二、请求与响应1. 请求与响应对象1.1 获取响应头信息1.2 获取发送到服务器的请求头信息 三、SSL 证书验证1. 忽略 SSL 证…...
协议幻变者:DeviceNet转ModbusTCP网关开启机器手臂智能新纪元
技术背景DeviceNet是一种广泛应用于工业自动化领域的现场总线标准,它能够实现控制器与现场设备之间的高效通信,常用于连接各种传感器、执行器以及其他工业设备,如机器人、电机驱动器等,具有实时性强、可靠性高的特点。而ModbusTCP…...
自定义有序Map
package cn.ziqirj.common.utils;import lombok.Getter; import lombok.Setter;import java.util.ArrayList; import java.util.List;/*** 模拟Map集合,key不可重复,按插入顺序排序* author zhangji** param <T>*/ public class CustomOrderlyMap&…...
CA系统的设计(CA证书生成,吊销,数字签名生成)
CA系统概述 CA认证系统是一种基于公钥密码基础设施(PKI)的信息安全技术,它可以为网络通信双方提供身份认证、数据加密、数字签名等功能。CA认证系统的核心是证书授权机构(CA),它负责为用户(节点…...
流计算需要框架吗?SPL 可能是更好的选择
流数据源通常是动态、无界的,看起来与静态、有限的批数据源区别较大,传统的数据库技术在架构上难以直接处理流数据源,只能让位于后来者。heron\samza\storm\spark\flink等计算框架最先完成突破,在流计算技术中占得先发优势。这些框…...
Vue-Router之嵌套路由
在路由配置中,配置children import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const router new VueRouter({mode: history,base: import.meta.env.BASE_URL,routes: [{path: /,redirect: /home},{path: /home,name: home,component: () &…...
MySQL 读写分离
MySQL 读写分离 一、配置主库(Master) 1.修改主库的配置文件 修改主库的 my.cnf 配置文件,生成二进制日志 (binary log) 和服务器唯一ID,这是实现主从复制的必要配置 [mysqld] # skip-grant-tables userroot port3306 basedir/usr/local/mysql datad…...
记一次音频无输出的解决方案
啊啊啊,刷个抖音就发现个死电脑死都不出声,捣鼓了一天才解决 打开wav文件时,提示错误找不到音频播放设备 0xc00d36fa 起初以为是声卡坏了,就到官网下载、更新了声卡驱动。无用什么驱动精灵也检测了,但也测不出啥来。…...
3D数学基础2
矩阵的行列式 在任意方阵中都存在至少一个标量,称作该方阵的行列式。在线性代数中,行列式有很多有用的性质 线性运算法则 方阵 M M M的行列式记作 ∣ M ∣ |M| ∣M∣或“det M”。非方阵矩阵的行列式是未定义的。 注意,在书写行列式时&…...
Java开发生态2024年度总结报告
1 关键要点 尽管数据显示 Java 17 是最常用 JDK,但其用户占比并未超过半数。根据 New Relic 2024 Java 生态系统状态报告,Java 17、11 和 8 的用户比例分别为 35%、33% 和 29%。New Relic 数据中所谓“快速采用”指 Java 21 的采用率仅为 1.4%。虽相较 J…...
1月第三讲:Java子线程无法获取Attributes的解决方法
在Java多线程编程中,开发者经常会遇到子线程无法获取主线程设置的Attributes的问题。Attributes通常用于存储与当前线程相关的数据,尤其在Web应用中,它们常用于请求上下文的管理。然而,由于Java线程是独立运行的,每个线…...
更新金碟云星空单据供应商和币别
--应付单 select FSUPPLIERID from [dbo].[T_AP_PAYABLE] where FBILLNO=AP2024121670 select FSUPPLIERID,FCURRENCYID,* from [dbo].[T_AP_PAYABLE] where FBILLNO=AP2024121670 -- update T_AP_PAYABLE set FSUPPLIERID=100567 where FBILLNO=AP2024121670 -- update T_…...
from memory cache 修复记录
背景 浏览器的页签图标,不想要了 改代码:设置浏览器页签的代码 本地环境测试,没有问题,一次性修改成功 于是打包,部署到测试环境,然而,还是有 接下的解决方法: 1、清除浏览器缓…...
spring入门程序
安装eclipse https://blog.csdn.net/qq_36437991/article/details/131644570 新建maven项目 安装依赖包 pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation&quo…...
用于实现无缝滚动效果的vue-seamless-scroll插件
它通常用于在网页或应用中实现内容的自动滚动效果,如新闻公告、图片轮播等,支持横向和纵向滚动,并且可以自定义滚动速度、方向等参数,适合展示一些需要持续循环展示的信息。 在Vue2项目中使用vue-seamless-scroll插件的步骤如下&…...
借助 FinClip 跨端技术探索鸿蒙原生应用开发之旅
在当今数字化浪潮汹涌澎湃的时代,移动应用开发领域正经历着深刻的变革与创新。鸿蒙操作系统的崛起,以其独特的分布式架构和强大的性能表现,吸引了众多开发者的目光。而FinClip 跨端技术的出现,为开发者涉足鸿蒙原生应用开发提供了…...
【机器学习】机器学习的基本分类-自监督学习-对比学习(Contrastive Learning)
对比学习是一种自监督学习方法,其目标是学习数据的表征(representation),使得在表征空间中,相似的样本距离更近,不相似的样本距离更远。通过设计对比损失函数(Contrastive Loss)&…...
python之eval函数
功能:将字符串str当成有效的表达式来求值并返回计算结果 语法:eval(source,[,globals[,locals]])->value 参数: source:一个python表达式或函数compile()返回的代码对象globals:可选。必须是dictionarylocals&am…...
NXP i.MX8系列平台开发讲解 - 5.3 调试篇(二) - 掌握Dynamic debug调试
专栏文章目录传送门:返回专栏目录 Hi, 我是你们的老朋友,主要专注于嵌入式软件开发,有兴趣不要忘记点击关注【码思途远】 文章目录 目录 掌握Dynamic debug调试 1. 认识Dynamic debug 2. 内核配置 3. 使用Dynamic debug 3.1 查看当前的…...
QT----------常用界面组件的使用
一、QComboBox 类 主要功能:提供一个下拉列表,用户可以从中选择一个或多个选项。 #include <QApplication> #include <QComboBox> #include <QVBoxLayout> #include <QWidget> #include <QMessageBox>int main(int argc…...
重新整理机器学习和神经网络框架
本篇重新梳理了人工智能(AI)、机器学习(ML)、神经网络(NN)和深度学习(DL)之间存在一定的包含关系,以下是它们的关系及各自内容,以及人工智能领域中深度学习分支对比整理。…...
AJAX详解
AJAX是前后端交互的重要工具 结合前后端交互基础理解:前后端交互详解(建议收藏)-CSDN博客 1. AJAX - 到底什么是Ajax? ajax 全名 async javascript and XML(异步JavaScript和XML),是一种用于向服务器异步发送 HTTP 请求并接收响应的技术。 XML 指可扩…...
golang中的异常处理机制
今天是2024最后一天,祝大家新年梦想成真,继续我的魅力golang,昨天发的错误处理,是明显的可预见、可恢复的问题,然而,不可预见的问题,往往更多,golang也有自己的一套,完全…...
HTML5 开关(Toggle Switch)详细讲解
HTML5 开关(Toggle Switch)详细讲解 1. 任务概述 开关(Toggle Switch)是一种用于表示二元状态(如开/关)的用户界面控件。用户可以通过点击开关来切换状态,常见于设置选项、开关功能等场景。 2…...