log4j2配置解析

log4j2自定义动态配置日志 项目需求 1.平台日志:Spring Boot项目中接入log4j2日志,公共配置作平台日志。 2.业务日志:为了方便定位业务问题自定义动态日志,根据不同业务输出不同名称的日志文件。 思路分析 第一个需求比较容易,网上教程资料非常多,多注意细节。第二个需求网上资料就很少了,需要去看一些源码信息了解日志打印过程使用的方法,然后根据业务需求做一个公共类:用户调用工具方法输入业务名称、日志路径等参数自定... 阅读详情
1. 添加依赖

在一般项目中使用Log4j2至少需要引用log4j-api-2.x和log4j-core-2.x这两个jar包(老版本),现在只需引入以下一个依赖即可,但是如果想桥接至slf4j,需要额外依赖(两者关系参考另一文章Java日志框架:slf4j作用及其实现原理)

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.12.0</version>
</dependency>

<!-- slf4j与log4j之间的桥接包-->
<dependency>
   	<groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency>

在spring boot项目中使用Log4j2

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <!-- 排除spring boot默认日志logback -->
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <dependency>
        <!--同时引入这两个依赖时,因为该jar依赖于前者,所以只需在前者中排除掉自带的logging依赖即可 -->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>      
        </dependency>

        <!-- 引入log4j2依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

依赖添加完成后,我们看一下都有什么jar包
在这里插入图片描述
第一个jar的作用是将log4j2与slf4j之间的桥接包,起绑定作用
第二个以及第三个是log4j2的核心包
第四个是java.util.logging.Logger与slf4j之间的桥接包

2. 添加配置文件

配置文件的加载主要逻辑在ConfigurationFactory这个类中,类容较多,能力有限不做过多分析,如深究,建议从
org.apache.logging.log4j.core.LoggerContext中start方法开始debug跟。

package org.apache.logging.log4j.core.config;
// **************略****************
public abstract class ConfigurationFactory extends ConfigurationBuilderFactory {

    public ConfigurationFactory() {
        super();
        // TEMP For breakpoints
    }

    /**
     * Allows the ConfigurationFactory class to be specified as a system property.
     */
    public static final String CONFIGURATION_FACTORY_PROPERTY = "log4j.configurationFactory";
    /**
     * Allows the location of the configuration file to be specified as a system property.
     */
    public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";

配置文件可以手动指定,但我们通常的选择是只提供文件,让log4j自己去找,log4j有默认的4个格式工厂,但它支持扩充(这里我不知道该怎么描述,建议往下看),可以加载其他自定义的工厂实现,如springBoot jar包中的工厂实现(第5个)

static List<ConfigurationFactory> getFactories() {
        return factories;
    }

每个工厂支持一个或多个后缀,分别是{.properties},{.yml以及.yaml},{.jsn以及.json},{.xml以及*},{.springBoot}
在这里插入图片描述
如果什么都没配置,springBoot项目中会自动生成一个默认配置。

3. 源码简单阅读

想了想,既然看了,还是写点啥吧,org.apache.logging.log4j.core.config.ConfigurationFactory
这里是不提供配置文件的springBoot项目的debug跟踪阅读源码放式,所以解读有限
在这里插入图片描述图片来自https://blog.youkuaiyun.com/sweetyi/article/details/104942310

 private void reconfigure(final URI configURI) {
        final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null;
        LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}",
                contextName, configURI, this, cl);
        // 贴上这段代码主要是学习一下ConfigurationFactory.getInstance()这个方法
        final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl);
        // ********略*******
}

public static ConfigurationFactory getInstance() {
        // volatile works in Java 1.6+, so double-checked locking also works properly
        // noinspection DoubleCheckedLocking
        if (factories == null) {
            LOCK.lock();
            try {
                if (factories == null) {
                    final List<ConfigurationFactory> list = new ArrayList<>();
                    // 检查一下,有没有手动指定额外的配置工厂
                    final String factoryClass = PropertiesUtil.getProperties().getStringProperty(CONFIGURATION_FACTORY_PROPERTY);
                    if (factoryClass != null) {
                        addFactory(list, factoryClass);
                    }
                    final PluginManager manager = new PluginManager(CATEGORY);
                    // 这里就是加载配置工厂的逻辑了,springBoot自己实现的工厂就是在这里被加载进来的,有兴趣的可以自己去看一下这个方法的源码
                    manager.collectPlugins();
                    final Map<String, PluginType<?>> plugins = manager.getPlugins();
                    final List<Class<? extends ConfigurationFactory>> ordered = new ArrayList<>(plugins.size());
                    for (final PluginType<?> type : plugins.values()) {
                        try {
                            ordered.add(type.getPluginClass().asSubclass(ConfigurationFactory.class));
                        } catch (final Exception ex) {
                            LOGGER.warn("Unable to add class {}", type.getPluginClass(), ex);
                        }
                    }
                    Collections.sort(ordered, OrderComparator.getInstance());
                    for (final Class<? extends ConfigurationFactory> clazz : ordered) {
                        addFactory(list, clazz);
                    }
                    // see above comments about double-checked locking
                    //noinspection NonThreadSafeLazyInitialization
                    factories = Collections.unmodifiableList(list);
                }
            } finally {
                LOCK.unlock();
            }
        }

        LOGGER.debug("Using configurationFactory {}", configFactory);
        /**
        * private static volatile List<ConfigurationFactory> factories = null;
		* private static ConfigurationFactory configFactory = new Factory();
   		* 上面的步骤是初始化factories ,实际返回的是ConfigurationFactory的内部实现类Factory
        */
        return configFactory;
    }

factories 最后包含了Factory以外的5个配置工厂实现类,这5个工厂是又排序的,决定了配置文件的查找顺序,这里截图不太合适,正确的顺序是Properties,Yaml,Json,Xml,SpringBoot
在这里插入图片描述
从包名可以看出,log4j包中是不含SpirngBoot配置工厂的,所以非springBoot项目,如果不提供配置文件的话,它是不会有默认配置的。

public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation, final ClassLoader loader) {
  		// ********略*******
        // 先判断类加载器是否为null
        if (loader == null) {
            return getConfiguration(loggerContext, name, configLocation);
        }
        // 如果加载器不为null,且URL资源有效,则尝试解析并返回配置
        if (isClassLoaderUri(configLocation)) {
        	// 解析路径
     		final String path = extractClassLoaderUriPath(configLocation);
            final ConfigurationSource source = ConfigurationSource.fromResource(path, loader);
            if (source != null) {
                final Configuration configuration = getConfiguration(loggerContext, source);
                if (configuration != null) {
                    return configuration;
                }
            }
        }
        return getConfiguration(loggerContext, name, configLocation);
    }

  // 后面这些就是解析URI的步骤了,可能需要一些URI知识点
   static boolean isClassLoaderUri(final URI uri) {
        if (uri == null) {
            return false;
        }
        final String scheme = uri.getScheme();
        return scheme == null || scheme.equals(CLASS_LOADER_SCHEME) || scheme.equals(CLASS_PATH_SCHEME);
    }

    static String extractClassLoaderUriPath(final URI uri) {
        return uri.getScheme() == null ? uri.getPath() : uri.getSchemeSpecificPart();
    }

	// 这个方法比较重要,配置文件的查找
    public static ConfigurationSource fromResource(final String resource, final ClassLoader loader) {
    	// 通过类加载器查找配置文件的URL,这里我其实也想去了解一下,就不写在这里了
        final URL url = Loader.getResource(resource, loader);
        if (url == null) {
            return null;
        }
        InputStream is = null;
        try {
            is = url.openStream();
        } catch (final IOException ioe) {
            ConfigurationFactory.LOGGER.catching(Level.DEBUG, ioe);
            return null;
        }
        if (is == null) {
            return null;
        }

        if (FileUtils.isFile(url)) {
            try {
                return new ConfigurationSource(is, FileUtils.fileFromUri(url.toURI()));
            } catch (final URISyntaxException ex) {
                // Just ignore the exception.
                ConfigurationFactory.LOGGER.catching(Level.DEBUG, ex);
            }
        }
        return new ConfigurationSource(is, url);
    }

	private static final String PROTOCOL_FILE = "file";
    private static final String JBOSS_FILE = "vfsfile";

    public static boolean isFile(final URL url) {
        return url != null && (url.getProtocol().equals(PROTOCOL_FILE) || url.getProtocol().equals(JBOSS_FILE));
    }
// 这是ConfigurationFactory的默认方法,仅发现某个工厂假如支持"*"格式时会被调用,实在有点绕,没读明白,不能理解意图,跳过
 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
        if (!isActive()) {
            return null;
        }
        if (configLocation != null) {
            final ConfigurationSource source = ConfigurationSource.fromUri(configLocation);
            if (source != null) {
                return getConfiguration(loggerContext, source);
            }
        }
        return null;
    }

// 这是Factory对上面方法的覆盖,也解释过了 ConfigurationFactory.getInstance()返回的是Factory实例,所以debug跟下来调用的也是这个
 public Configuration getConfiguration(final LoggerContext loggerContext, final String name, final URI configLocation) {
            if (configLocation == null) {
            	// 又是查环境变量,直接跳过
                final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties()
                        .getStringProperty(CONFIGURATION_FILE_PROPERTY));
                if (configLocationStr != null) {
                    final String[] sources = configLocationStr.split(",");
                    if (sources.length > 1) {
                        final List<AbstractConfiguration> configs = new ArrayList<>();
                        for (final String sourceLocation : sources) {
                            final Configuration config = getConfiguration(loggerContext, sourceLocation.trim());
                            if (config != null && config instanceof AbstractConfiguration) {
                                configs.add((AbstractConfiguration) config);
                            } else {
                                LOGGER.error("Failed to created configuration at {}", sourceLocation);
                                return null;
                            }
                        }
                        return new CompositeConfiguration(configs);
                    }
                    return getConfiguration(loggerContext, configLocationStr);
                }
                // 这里就是去匹配*格式,debug跟完没有什么作用,跳过算了
                for (final ConfigurationFactory factory : getFactories()) {
                    final String[] types = factory.getSupportedTypes();
                    if (types != null) {
                        for (final String type : types) {
                            if (type.equals(ALL_TYPES)) {       
                                final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
                                if (config != null) {
                                    return config;
                                }
                            }
                        }
                    }
                }
            } else {
                // configLocation != null
                final String configLocationStr = configLocation.toString();
                for (final ConfigurationFactory factory : getFactories()) {
                    final String[] types = factory.getSupportedTypes();
                    if (types != null) {
                        for (final String type : types) {
                            if (type.equals(ALL_TYPES) || configLocationStr.endsWith(type)) {
                                final Configuration config = factory.getConfiguration(loggerContext, name, configLocation);
                                if (config != null) {
                                    return config;
                                }
                            }
                        }
                    }
                }
            }
			// 重点就是在这个方法了,以各种不同组合的参数去查找配置
            Configuration config = getConfiguration(loggerContext, true, name);
            if (config == null) {
                config = getConfiguration(loggerContext, true, null);
                if (config == null) {
                    config = getConfiguration(loggerContext, false, name);
                    if (config == null) {
                        config = getConfiguration(loggerContext, false, null);
                    }
                }
            }
            if (config != null) {
                return config;
            }
            LOGGER.error("No Log4j 2 configuration file found. " +
                    "Using default configuration (logging only errors to the console), " +
                    "or user programmatically provided configurations. " +
                    "Set system property 'log4j2.debug' " +
                    "to show Log4j 2 internal initialization logging. " +
                    "See https://logging.apache.org/log4j/2.x/manual/configuration.html for instructions on how to configure Log4j 2");
            return new DefaultConfiguration();
        }
 private Configuration getConfiguration(final LoggerContext loggerContext, final boolean isTest, final String name) {
            final boolean named = Strings.isNotEmpty(name);
            final ClassLoader loader = LoaderUtil.getThreadContextClassLoader();
            for (final ConfigurationFactory factory : getFactories()) {
                String configName;
                final String prefix = isTest ? TEST_PREFIX : DEFAULT_PREFIX;
                final String [] types = factory.getSupportedTypes();
                if (types == null) {
                    continue;
                }

                for (final String suffix : types) {
                    if (suffix.equals(ALL_TYPES)) {
                        continue;
                    }
                    configName = named ? prefix + name + suffix : prefix + suffix;
					// 逻辑很简单,生成配置名称,根据类加载器查找指定配置
                    final ConfigurationSource source = ConfigurationSource.fromResource(configName, loader);
                    if (source != null) {
                        if (!factory.isActive()) {
                            LOGGER.warn("Found configuration file {} for inactive ConfigurationFactory {}", configName, factory.getClass().getName());
                        }
                        return factory.getConfiguration(loggerContext, source);
                    }
                }
            }
            return null;
        }
log4j 源码解析_Log4j2源码分析系列:(一)配置加载 前言在实际开发项目中,日志永远是一个绕不开的话题。本系列文章试图以slf4j和log4j2日志体系为例,从源码角度分析日志工作原理。置加载过程为主线,描述其工作流程;影响不大的旁枝细节会忽略,有兴趣的读者可自行查阅源码。2.多图预警!用电脑查看效果更佳。3.尽量动手操作,以加深理解。环境准备阅读源码前,请确保引入了sl学习日志框架,首先要熟悉各类日志框架,这里推荐两篇文章,就不再赘述了。我们会拿... 阅读详情

相关推荐

深入解析Log4j-1.2.9:配置与应用

Apache Log4j 是一个功能强大的Java日志记录库,广泛应用于企业级应用和开源项目中。它允许开发者记录不同级别的日志信息到各种目的地,并支持多种日志记录方式。在Log4j中,日志级别用于确定日志消息的严重性。主要有以下几种级别:DEBUG: 用于调试目的,记录详细的程序流程信息。INFO: 记录应用程序运行状态的一般信息。WARN: 记录可能不期望发生但不会影响程序运行的事件。ERROR: 记录发生了错误的情况,但可能并不致命。FATAL。

weixin_33773084的博客 989

NoSuchMethodError: org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration

Application startup failed java.lang.NoSuchMethodError: org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(Lorg/apache/logging/log4j/core/LoggerContext;Lorg/apache/logging/log4j/core/config/ConfigurationSource;)Lorg/apache/logging/l

xianganyu8801的博客 4811

log4j2必需jar包

log4j2必需jar包,包含log4j-api-2.11.1.jar和log4j-core-2.11.1.jar

(四)、log4j2相关依赖

log4j2

宙斯的财富 9215

Cursor设置界面汉化保姆级教程:手把手教你修改JS文件实现中文界面(附避坑指南)

本文提供Cursor编辑器设置界面汉化的详细教程,从定位JS文件到安全修改实现中文界面,包含必备工具清单、文件路径指引和常见问题解决方案。通过手把手教学帮助用户轻松完成汉化,提升使用体验,特别适合不熟悉英文界面的开发者。

weixin_29007809的博客 1415

CMU的local_planner学习笔记

ros::Subscriber subOdometry = nh.subscribe//当接收到/state_estimation话题消息更新时启动odometryHandler回调函数 (消息格式:nav_msgs::Odometry消息内容:关于机器人或车辆的位置和方向(姿态)信息)pcl::PointCloud::Ptr freePaths(new pcl::PointCloud());

qq_35971623的博客 3881

springboot-log4j启动异常(java.lang.AbstractMethodError)

目录 1. 问题描述 2. 问题排查 1. 问题描述 springboot 2.0.4 通过 springboot 内置 tomcat 启动服务无异常,但是使用外置 tomcat 启动报错,错误信息如下: Caused by: java.lang.AbstractMethodError: org.apache.logging.log4j.core.config.ConfigurationFactory.getConfiguration(Lorg/apache/logging/log4j/cor

sxsAffable的博客 3426

mysql9.0windows安装

将这里的位置修改为你刚刚创建并复制data目录的地址即可,win11的系统使用vscode修改之后,会让你确认开启更高权限以进行保存,比较方便,window10不需要确认,修改后可以直接保存。:在修改之前,最好将下图文件进行备份,将原始的文件保存好一份,以防更改了配置之后,导致mysql服务报错,无法启动,备份好的话直接将有问题的配置文件给替换就可以,无需重新安装一次mySql。双击下载的msi文件进行安装。安装有问题的,可以直接进行卸载,新本的mySql会将注册表中的数据自动进行清除,还是很方便的。

m0_74824123的博客 6448

log4j:log4j2配置文件解析

本文主要对如下配置文件进行解析: status=info name=PropertiesConfig rootLogger.level=info rootLogger.appenderRef.stdout.ref=STDOUT rootLogger.appenderRef.rolling.ref=RollingFile appender.stdout.type=Console ap...

weixin_38569499的博客 1万+

(一)利用Python实现数据集读取,Python基本文件操作介绍

机器学习是计算机对大量数据的分析过程,在机器学习的实际项目中,通常都需要准备数据集,数据集通常包含的数据数量是庞大的。例如,在处理计算机视觉领域的项目时,每一张图片都是一个单独的文件,为了提高模型训练的效果,图片数量通常会比较多,因此需要合理且高效的操作将所有的图片数据读取。本篇旨在介绍如何用Python对海量文件进行遍历,也是机器学习实践的第一步。.........

ZZR2631574030的博客 6357

西门子828D/840DSL数控机床产量数据采集实战:手把手教你绕过授权限制(附Demo源码)

本文详细介绍了西门子828D/840DSL数控机床产量数据采集的实战技术,包括绕过授权限制的替代方案和实现方法。通过分析通信协议、配置参数和数据处理,提供了一套高效且合规的数据采集解决方案,并附有Demo源码,帮助技术人员快速上手。

weixin_28278377的博客 763

log4j2的配置文件解析

一、背景 昨天了解了一下slf4j和log4j2,想要进行总结记录,配置步骤十分简单,唯一需要具体了解的就是log4j2.xml的配置,于是找到了这篇博文,配置讲解十分详细,便转载作记录,再次感谢阿豪聊干货。以下原文:     最近由于项目的需要,我们把log4j 1.x的版本全部迁移成log4j 2.x 的版本,那随之而来的slf4j整合log4j的配置(使用Slf4j集成Log4j2构建...

HELLOW,文浩 638

uniapp实战:mui-player插件如何完美适配m3u8/flv直播流(附完整代码)

本文详细介绍了如何在Uniapp中使用mui-player插件完美适配m3u8和flv直播流,提供从基础配置到高级优化的全流程解决方案。通过动态加载策略、响应式布局和内存管理,实现跨平台稳定播放,适用于企业级直播应用开发。

weixin_29001655的博客 237

log4j2配置文件log4j2.xml解析

转载网址:http://www.cnblogs.com/hafiz/p/6170702.html一、背景  最近由于项目的需要,我们把log4j 1.x的版本全部迁移成log4j 2.x 的版本,那随之而来的slf4j整合log4j的配置(使用Slf4j集成Log4j2构建项目日志系统的完美解决方案)以及log4j2配置文件的详解,就需要我们来好好聊一聊了。本文就专门来讲解下log4j2.xml配置

wenwenxiong的专栏 6223

Linux Kernel入门到精通系列讲解(RV-Kernel 篇) 5.6 在kernel 中实现系统复位和系统关机驱动

上一章节`Qemu`篇我们已经实现了我们`SOC`的`power reset`和 `power down` 寄存器,本章节我们就在`Linux driver`中去实现它

DSMGUOGUO的博客 544

定位教程7---旋转中心标定之方法二

手算相机相对机器人关系

Quintin 6230

Log4J2(六) - 配置工厂ConfigurationFactory的初始化过程-源码解析

分析Log4J2的配置工厂实例化以及初始化过程

sweetyi的专栏 2476

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

log4j2配置解析及发送log到kafka(xml/yml)

log4j2的优势 在异步,吞吐量等方面有极大的性能提升,Log4j2的性能为什么这么好https://www.jianshu.com/p/359b14067b9e maven <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api --> <dependency&gt...

Timmer的博客 1891

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

slf4j+log4j2使用及log4j2配置文件解析

slf4j+log4j2复制就可使用的最好配置!

MemoForward的博客 1831

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

log4j2.xml配置解析

日志器分根日志器Root和自定义日志器,当根据日志名字获取不到指定的日志器时就使用Root作为默认的日志器,自定义时需要指定每个Logger的名称name(对于命名可以以包名作为日志的名字,不同的包配置不同的级别等),日志级别level,相加性additivity(是否继承下面配置的日志器), 对于一般的日志器(如Console、File、RollingRandomAccessFile)一般需要配置一个或多个输出源AppenderRef;NoSql:MongoDb, 输出到MongDb数据库中。

hw120219的博客 2160

log4j2.xml配置文件元素解析

log4j2.xml配置文件元素解析配置文件展示log4j2配置文件整体结构对于Appender的理解对于Logger的理解Appender的常用的实现类有:标签详解及可包含字标签元素ConsoleFile、 RandomAccessFile代码示例:属性解释:RollingFile 、 RollingRandomAccessFile示例代码:Filters常用的Filter实现类有:Policy...

qq_32281025的博客 1230

log4j2xml配置解析

<?xml version="1.0" encoding="UTF-8"?> 2 <!-- 3 status : 这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,会看到log4j2内部各种详细输出。 4 因此我们直接设置成OFF 5 --> 6 <Configuration status="OFF"> 7 <!-- 配置输出端 --> 8 <Appenders> 9 .

u012149181的博客 2493

Log4j 2架构解析与生产环境实战配置指南

日志管理是构建可观测性系统的基石,其核心在于高效、可靠地记录和输出应用运行信息。从原理上看,现代日志框架通过解耦日志采集、过滤、格式化与输出等职责,并引入异步无锁等高性能机制,来确保在高并发场景下不影响业务主流程。其技术价值在于为分布式系统提供了关键的可观测性数据,是问题定位、性能分析和安全审计的重要依据。应用场景广泛覆盖了从日常开发调试到线上故障排查的全生命周期。本文聚焦于Apache Log4j 2这一高性能日志框架,深入剖析其采用**LMAX Disruptor**实现无锁异步的架构革新,并详解如何利

weixin_32932149的博客 312

Log4j2 部分配置解析

没有一件工作是旷日持久的,除了那件你不敢拌着手进行的工作。

相信自己有能力,那么你就真的会有! 438

Log4j2 的 入门和配置文件解析

Apache Log4j 2是对Log4j的升级版,参考了logback的一些优秀的设计,并且修复了一些问题,因此带 来了一些重大的提升,主要有: 异常处理,在logback中,Appender中的异常不会被应用感知到,但是在log4j2中,提供了一些异常处理机制。 性能提升, log4j2相较于log4j 和logback都具有很明显的性能提升,后面会有官方测试的数据。 自动重载配置,参考了logback的设计,当然会提供自动刷新参数配置,最实用的就是我们在生产上可以动态的修改日志的级别而不需要重启应用

weixin_45417821的博客 400
上一篇: Java日志框架:slf4j作用及其实现原理
下一篇: log4j默认配置
MrMoving
博客等级 码龄10年 54粉丝 145原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值