亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot日志框架之Log4j2快速入門(mén)與參數(shù)詳解

 更新時(shí)間:2023年05月30日 10:32:25   作者:莫念Program  
本文介紹了SpringBoot日志框架log4j2的基本使用和配置方法,包括將日志輸出到控制臺(tái)、文件、Elasticsearch和Kafka,多個(gè)輸出目的地的配置,異步日志記錄器的使用以及l(fā)og4j2.xml配置文件的詳細(xì)語(yǔ)法和參數(shù)含義,需要的朋友可以參考下

Quick Start

在SpringBoot中使用log4j2日志框架,只需三步:

  • 引入依賴(lài)
  • 配置log文件
  • 獲取Logger實(shí)例并輸出日志

引入依賴(lài)

dependencies {
    implementation 'org.apache.logging.log4j:log4j-core:2.14.1'
    implementation 'org.apache.logging.log4j:log4j-api:2.14.1'
    implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.14.1"
    implementation('org.springframework.boot:spring-boot-starter') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

為了避免日志框架之間的沖突,建議在使用Log4j2時(shí)將其他的日志框架排除掉,例如在build.gradle文件中排除Spring Boot默認(rèn)的Logback日志框架

配置log文件

創(chuàng)建Log4j2的配置文件log4j2.xml,可以放在src/main/resources目錄下或指定的目錄下。

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

上面的配置文件定義了一個(gè)名為Console的Appender,用于將日志輸出到控制臺(tái)。它使用了PatternLayout來(lái)定義日志輸出格式,包含了日期、線(xiàn)程、日志級(jí)別、Logger名稱(chēng)和消息等信息。在Loggers中,我們將根Logger的日志級(jí)別設(shè)置為info,并將Console Appender添加到根Lodagger中。

獲取Logger實(shí)例并輸出日志

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class MyService {
    private static final Logger logger = LogManager.getLogger(MyService.class);
    public void doSomething() {
        logger.debug("Debug message");
        logger.info("Info message");
        logger.warn("Warning message");
        logger.error("Error message");
    }
}

使用LogManager獲取Logger實(shí)例,然后使用Logger的debug、info、warn和error方法來(lái)記錄不同級(jí)別的日志。

這是日志輸出結(jié)果,機(jī)智的朋友可能已經(jīng)發(fā)現(xiàn)了,這段輸出里沒(méi)有debug級(jí)別的日志,這是因?yàn)樵谀J(rèn)情況下,Logback 只會(huì)輸出 INFO 級(jí)別及以上的日志信息。

我們把日志級(jí)別從info改成debug就可以輸出debug日志了

<Loggers>
  <Root level="debug">
    <AppenderRef ref="Console"/>
  </Root>
</Loggers>

@Slf4j注解

@Slf4j 是 Lombok 提供的一個(gè)注解,用于在編譯時(shí)自動(dòng)生成日志變量。

dependencies {
    implementation 'org.apache.logging.log4j:log4j-core:2.14.1'
    implementation 'org.apache.logging.log4j:log4j-api:2.14.1'
    implementation "org.apache.logging.log4j:log4j-slf4j-impl:2.14.1"
    implementation('org.springframework.boot:spring-boot-starter') {
        exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
    }
}

使用 @Slf4j 注解需要引入 lombok 和 SLF4J 的依賴(lài)。

import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyClass {
    public void myMethod() {
        log.info("這是一條日志");
    }
}

@Slf4j 注解會(huì)自動(dòng)生成一個(gè)名為 log 的日志變量,我們可以直接使用 log 對(duì)象來(lái)記錄日志。

log4j2.xml 詳解

log4j2.xml 是 log4j 2.x 版本的配置文件格式,用于配置日志記錄器的行為。它可以定義多個(gè)日志記錄器、日志輸出器和日志格式。

標(biāo)簽簡(jiǎn)介

以下是一些 log4j2.xml 中的重要標(biāo)簽:

  • <Configuration>:定義整個(gè)配置文件的根元素,它有一個(gè) status 屬性,用于控制日志框架的日志輸出級(jí)別。status 屬性的值可以是 ALL、TRACE、DEBUG、INFO、WARN、ERROR、FATAL 或 OFF 中的任何一個(gè),默認(rèn)值為 OFF。
  • <Appenders>:定義日志輸出器的集合,可以包含多個(gè) Appender。每個(gè) Appender 可以有自己的日志輸出方式和格式化方式,以滿(mǎn)足不同的需求。
  • <Logger>:定義一個(gè) Logger 對(duì)象,它可以有自己的日志級(jí)別、Appenders 和過(guò)濾器等屬性。Logger 元素還可以通過(guò)子元素 <AppenderRef> 來(lái)引用一個(gè)或多個(gè) Appenders,將它們附加到該 Logger 上。
  • <Root>:定義 Root Logger 對(duì)象,它是所有 Logger 的父 Logger。它的級(jí)別通常設(shè)置為最低級(jí)別,以便將所有日志消息傳遞到其他 Logger 或 Appender。Root 元素也可以通過(guò)子元素 <AppenderRef> 來(lái)引用一個(gè)或多個(gè) Appenders,將它們附加到 Root Logger 上。
  • <Filter>:定義一個(gè)或多個(gè)過(guò)濾器,用于控制哪些日志消息被記錄和輸出。過(guò)濾器可以根據(jù)日志級(jí)別、消息內(nèi)容、時(shí)間戳等條件進(jìn)行過(guò)濾。
  • <PatternLayout>:定義日志格式化器,用于將日志消息格式化成一行一行的文本。PatternLayout 可以使用一系列占位符,表示日志消息的不同部分,例如時(shí)間戳、線(xiàn)程名、日志級(jí)別、類(lèi)名、方法名、消息內(nèi)容等。
  • <RollingFile>:定義一個(gè) RollingFile Appender,用于將日志輸出到文件,并實(shí)現(xiàn)滾動(dòng)文件的功能。RollingFile Appender 可以按照時(shí)間、文件大小等條件進(jìn)行滾動(dòng),并設(shè)置最多保留多少個(gè)日志文件。
  • <Console>:定義一個(gè) Console Appender,用于將日志輸出到控制臺(tái)。
  • <Elasticsearch>:定義一個(gè) Elasticsearch Appender,用于將日志輸出到 Elasticsearch 中。

輸出到控制臺(tái)

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>

該文件定義了一個(gè)名為 Console 的 Appender,用于將日志輸出到控制臺(tái)。

PatternLayout格式化字符串含義如下:

  • %d{yyyy-MM-dd HH:mm:ss.SSS}:輸出日志時(shí)間的格式,其中yyyy表示四位年份,MM表示兩位月份,dd表示兩位日期,HH表示24小時(shí)制的小時(shí)數(shù),mm表示分鐘數(shù),ss表示秒數(shù),SSS表示毫秒數(shù)。
  • [%t]:輸出線(xiàn)程名稱(chēng)。
  • %-5level:輸出日志級(jí)別,其中-表示左對(duì)齊,5表示占位符寬度,level表示日志級(jí)別。
  • %logger{36}:輸出logger名稱(chēng),其中36表示logger名稱(chēng)的最大寬度。
  • %msg%n:輸出日志消息和換行符。

該文件還定義了一個(gè) Root logger,將日志級(jí)別設(shè)置為 info,表示只輸出 INFO 級(jí)別及以上的日志信息,并將它的 AppenderRef 設(shè)置為 Console。

輸出到文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <RollingFile name="RollingFile" fileName="/path/to/logs/myapp.log"
                     filePattern="/path/to/logs/myapp-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</Configuration>

這個(gè)配置文件中定義了一個(gè)名為 RollingFile 的 Appender,用于將日志輸出到文件。

RollingFile Appender 使用了 TimeBasedTriggeringPolicy 和 SizeBasedTriggeringPolicy,表示按時(shí)間和文件大小來(lái)滾動(dòng)文件,以避免日志文件過(guò)大。DefaultRolloverStrategy 表示最多保留 10 個(gè)日志文件。

輸出到多個(gè)文件:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <Routing name="Routing">
            <Routes pattern="$${ctx:logFileName}">
                <Route>
                    <File name="file" fileName="/path/to/logs/${ctx:logFileName}.log">
                        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
                    </File>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Routing"/>
        </Root>
    </Loggers>
</Configuration>

這個(gè)配置文件中定義了一個(gè)名為 Routing 的 Appender,用于按照日志文件名將日志輸出到不同的文件中。Routing Appender 使用了 Routes 和 Route 元素,將日志按照日志文件名的不同路由到不同的 File Appender 中,實(shí)現(xiàn)了將日志輸出到多個(gè)文件的功能。

輸出Elasticsearch

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="org.apache.logging.log4j.core,com.fasterxml.jackson.databind.json">
  <Appenders>
    <Elasticsearch name="elasticsearch" type="http" index="log4j2" indexDateFormat="yyyy-MM-dd" ignoreExceptions="false">
      <ServerHost>localhost</ServerHost>
      <ServerPort>9200</ServerPort>
      <IndexType>doc</IndexType>
      <SourceHost>${env:HOSTNAME}</SourceHost>
      <JacksonJsonLayout compact="true" />
    </Elasticsearch>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="elasticsearch" />
    </Root>
  </Loggers>
</Configuration>

上述配置文件中,<Elasticsearch> 元素定義了 Elasticsearch Appender 的配置,其中包含了以下屬性:

  • name:指定 Appender 的名稱(chēng),可自定義。
  • type:指定 Elasticsearch 連接類(lèi)型,這里使用的是 HTTP連接方式。
  • index:指定 Elasticsearch 中的索引名稱(chēng)。
  • indexDateFormat:指定日志索引的日期格式。
  • ignoreExceptions:指定是否忽略異常,如果設(shè)置為 false,則在出現(xiàn)異常時(shí)會(huì)中斷應(yīng)用程序。
  • ServerHost:指定 Elasticsearch 服務(wù)器的主機(jī)名或 IP 地址。
  • ServerPort:指定 Elasticsearch 服務(wù)器的端口號(hào)。
  • IndexType:指定 Elasticsearch 索引類(lèi)型。
  • SourceHost:指定日志來(lái)源的主機(jī)名或 IP 地址。
  • JacksonJsonLayout:指定日志輸出的格式,這里使用了 JacksonJsonLayout。

配置多個(gè)Appenders

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="info">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
        </Console>
        <RollingFile name="RollingFile" fileName="/path/to/logs/myapp.log"
                     filePattern="/path/to/logs/myapp-%d{yyyy-MM-dd}-%i.log.gz">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <DefaultRolloverStrategy max="10"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Root>
    </Loggers>
</Configuration>

在這個(gè)例子中,我們定義了一個(gè)名為 Console 的 Appender 和一個(gè)名為 RollingFile 的 Appender。Console Appender 用于將日志輸出到控制臺(tái),RollingFile Appender 用于將日志輸出到文件。在 Loggers 元素中,我們將 Root logger 的 AppenderRef 分別設(shè)置為 Console 和 RollingFile,表示將日志同時(shí)輸出到控制臺(tái)和文件中。

每個(gè) Appender 必須有一個(gè)唯一的 name 屬性,用于在其他地方引用該 Appender。在 Loggers 元素中,可以通過(guò) AppenderRef 元素來(lái)引用一個(gè)或多個(gè) Appenders,并將它們附加到特定的 Logger 上。也可以通過(guò) Logger 元素來(lái)定義一個(gè)新的 Logger,并將其與一個(gè)或多個(gè) Appenders 關(guān)聯(lián)起來(lái)。

輸出到kafka

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="org.apache.logging.log4j.core,com.fasterxml.jackson.databind.json">
  <Appenders>
        <Kafka name="Kafka" topic="myTopic" syncSend="false">
            <Property name="bootstrap.servers">localhost:9092</Property>
            <Property name="acks">1</Property>
            <Property name="batch.size">32768</Property>
            <Property name="compression.type">snappy</Property>
            <Property name="retries">20</Property>
            <Property name="reconnect.backoff.ms">20000</Property>
            <Property name="retry.backoff.ms">20000</Property>
            <PatternLayout pattern="${LOG_PATTERN}" charset="utf-8"/>
        </Kafka>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="Kafka" />
    </Root>
  </Loggers>
</Configuration>

Kafka

  • topic 屬性:指定 Kafka 主題的名稱(chēng),這里設(shè)置為 myTopic。
  • bootstrap.servers 屬性:指定 Kafka 服務(wù)器的地址和端口號(hào),這里設(shè)置為 localhost:9092。
  • acks 屬性:指定 Kafka 生產(chǎn)者的確認(rèn)級(jí)別。這里設(shè)置為 1,表示只需要 Kafka 生產(chǎn)者收到消息就返回確認(rèn)消息。
  • batch.size 屬性:指定 Kafka 生產(chǎn)者批量發(fā)送消息的大小。這里設(shè)置為 32768。
  • compression.type 屬性:指定消息的壓縮類(lèi)型,這里設(shè)置為 snappy。
  • retries 屬性:指定 Kafka 生產(chǎn)者在發(fā)生錯(cuò)誤時(shí)的重試次數(shù)。這里設(shè)置為 20
  • reconnect.backoff.ms 屬性:指定 Kafka 生產(chǎn)者在重新連接到 Kafka 服務(wù)器之前的等待時(shí)間。這里設(shè)置為 20000 毫秒。
  • retry.backoff.ms 屬性:指定 Kafka 生產(chǎn)者在發(fā)生錯(cuò)誤時(shí)的重試等待時(shí)間。這里設(shè)置為 20000 毫秒。

配置異步日志記錄器

在 log4j2 中,可以使用異步日志記錄器來(lái)提高性能和吞吐量。

異步日志記錄器可以將日志事件放入一個(gè)隊(duì)列中,然后由另外的線(xiàn)程或線(xiàn)程池來(lái)處理隊(duì)列中的日志事件,從而降低了日志記錄對(duì)應(yīng)用程序的影響。

下面是在 log4j2.xml 中配置異步日志記錄器的示例:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
    <Properties>
        <Property name="LOG_PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT" follow="true">
            <PatternLayout pattern="${LOG_PATTERN}"/>
        </Console>
        <Async name="AsyncConsole" bufferSize="16384" queueSize="500" ringBufferSize="1024" blocking="false">
            <AppenderRef ref="Console"/>
        </Async>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="AsyncConsole"/>
        </Root>
    </Loggers>
</Configuration>

<Async> 元素是 Log4j2 中用于實(shí)現(xiàn)異步日志輸出的 Appender。以下是 <Async> 元素中各個(gè)參數(shù)的解釋?zhuān)?/p>

  • name:指定異步 Appender 的名稱(chēng),可自定義。
  • bufferSize:指定異步隊(duì)列的緩沖區(qū)大小,即可以同時(shí)緩存的日志事件的數(shù)量。當(dāng)隊(duì)列已滿(mǎn)時(shí),新的日志事件會(huì)被直接丟棄。
  • queueSize:指定異步隊(duì)列的容量,即可以緩存的日志事件的最大數(shù)量。當(dāng)超過(guò)此數(shù)量時(shí),新的日志事件會(huì)被直接丟棄。
  • ringBufferSize:指定異步隊(duì)列的環(huán)形緩沖區(qū)大小,這是一個(gè)循環(huán)隊(duì)列,大小必須是 2 的冪次方。如果未指定 bufferSize,則使用 ringBufferSize 作為緩沖區(qū)大小。
  • blocking:指定是否使用阻塞模式。如果設(shè)置為 true,則當(dāng)隊(duì)列已滿(mǎn)時(shí),新的日志事件將會(huì)被阻塞,直到隊(duì)列中有空閑位置。如果設(shè)置為 false,則當(dāng)隊(duì)列已滿(mǎn)時(shí),新的日志事件會(huì)被直接丟棄。
  • AppenderRef:指定異步 Appender 的輸出目的地。

以上就是SpringBoot日志框架之Log4j2快速入門(mén)與參數(shù)詳解的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot Log4j2入門(mén)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java實(shí)現(xiàn)圖片上加文字水印(SpringMVC + Jsp)

    java實(shí)現(xiàn)圖片上加文字水印(SpringMVC + Jsp)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)在圖片上加文字水印的方法,水印可以是圖片或者文字,操作方便,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • 一文徹底搞懂java多線(xiàn)程和線(xiàn)程池

    一文徹底搞懂java多線(xiàn)程和線(xiàn)程池

    當(dāng)一個(gè)服務(wù)器接受到大量短小線(xiàn)程的請(qǐng)求時(shí),使用線(xiàn)程池技術(shù)是非常合適的,它可以大大減少線(xiàn)程的創(chuàng)建和銷(xiāo)毀次數(shù),提高服務(wù)器的工作效率,這篇文章主要給大家介紹了如何通過(guò)一文徹底搞懂java多線(xiàn)程和線(xiàn)程池的相關(guān)資料,需要的朋友可以參考下
    2021-09-09
  • Java遞歸實(shí)現(xiàn)迷宮游戲

    Java遞歸實(shí)現(xiàn)迷宮游戲

    這篇文章主要介紹了如何利用Java遞歸方法實(shí)現(xiàn)迷宮游戲,下面文章會(huì)詳細(xì)的從為問(wèn)題描述開(kāi)始,清晰的解題思路以及詳細(xì)的代碼實(shí)現(xiàn),具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2021-12-12
  • 詳解SpringBoot接收參數(shù)的五種形式

    詳解SpringBoot接收參數(shù)的五種形式

    在Spring Boot中,接收參數(shù)可以通過(guò)多種方式實(shí)現(xiàn),本文給大家介紹了SpringBoot接收參數(shù)的五種形式,并通過(guò)代碼和圖文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • SpringBoot多數(shù)據(jù)源配置完整指南

    SpringBoot多數(shù)據(jù)源配置完整指南

    在復(fù)雜的企業(yè)應(yīng)用中,經(jīng)常需要連接多個(gè)數(shù)據(jù)庫(kù),Spring Boot 提供了靈活的多數(shù)據(jù)源配置方式,以下是詳細(xì)的實(shí)現(xiàn)方案,需要的朋友可以參考下
    2025-04-04
  • 深入理解Java中的EnumMap和EnumSet

    深入理解Java中的EnumMap和EnumSet

    這篇文章主要介紹了深入理解Java中的EnumMap和EnumSet,一般來(lái)說(shuō)我們會(huì)選擇使用HashMap來(lái)存儲(chǔ)key-value格式的數(shù)據(jù),考慮這樣的特殊情況,一個(gè)HashMap的key都來(lái)自于一個(gè)Enum類(lèi),這樣的情況則可以考慮使用本文要講的EnumMap,需要的朋友可以參考下
    2023-11-11
  • 基于Java實(shí)現(xiàn)QQ登錄注冊(cè)功能的示例代碼

    基于Java實(shí)現(xiàn)QQ登錄注冊(cè)功能的示例代碼

    這篇文章主要和大家分享如何利用Java語(yǔ)言實(shí)現(xiàn)QQ登錄、注冊(cè)等功能。本文主要應(yīng)用的技術(shù)有:GUI、JDBC、多線(xiàn)程等,需要的可以參考一下
    2022-05-05
  • 淺析java class 文件

    淺析java class 文件

    以下是對(duì)java中的class文件進(jìn)行了詳細(xì)的介紹,需要的朋友可以過(guò)來(lái)參考下
    2013-08-08
  • 關(guān)于Object中equals方法和hashCode方法判斷的分析

    關(guān)于Object中equals方法和hashCode方法判斷的分析

    今天小編就為大家分享一篇關(guān)于關(guān)于Object中equals方法和hashCode方法判斷的分析,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • spring boot國(guó)際化之MessageSource的使用方法

    spring boot國(guó)際化之MessageSource的使用方法

    這篇文章主要給大家介紹了spring boot國(guó)際化之MessageSource使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評(píng)論