log4j是如何获取logger的

ARM 汇编指令:LSL(逻辑左移) 和 LSR(逻辑右移) ARM 汇编中的 LSL(逻辑左移)和 LSR(逻辑右移)是基础移位指令,分别实现二进制位的左移和右移操作。LSL 低位补0,等效于乘以2^n;LSR 高位补0,等效于无符号除以2^n。这两个指令可以单独使用或与其他指令结合(如ADD、MOV等),利用ARM的"桶形移位器"硬件实现高效运算。关键特性包括:移位范围0-31(LSL)或1-32(LSR),可选更新标志位,以及与其他指令结合时的无额外开销优势。LSR与ASR(算术右移)的主要区别在于高位填充方式,分别适用于无符号和有符号数处理 阅读详情
// LogManager源码
public static Logger getLogger(final Class<?> clazz) {
    final Class<?> cls = callerClass(clazz);
    // 1. 先获取LoggerContext,然后通过LoggerContext获取logger
    return getContext(cls.getClassLoader(), false).getLogger(toLoggerName(cls));
}

 // 成员变量
private static volatile LoggerContextFactory factory;
     
public static LoggerContext getContext(final ClassLoader loader, final boolean currentContext) {
    try {
    	// 2. 该factory是内部属性LoggerContextFactory,在静态代码块中初始化(扫描类路径以查找所有日志实现,但是只有一个会被使用)
        return factory.getContext(FQCN, loader, null, currentContext);
    } catch (final IllegalStateException ex) {
        LOGGER.warn(ex.getMessage() + " Using SimpleLogger");
        return new SimpleLoggerContextFactory().getContext(FQCN, loader, null, currentContext);
    }
}

// Log4jContextFactory (implements LoggerContextFactory)
public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext,
                                final boolean currentContext) {
    // 这里就跟到了下面那段断码
    final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext);
    if (externalContext != null && ctx.getExternalContext() == null) {
        ctx.setExternalContext(externalContext);
    }
    if (ctx.getState() == LifeCycle.State.INITIALIZED) {
    	// 如果LoggerContext刚初始化完成,执行start方法,后续会分析
        ctx.start();
    }
    return ctx;
}
	
// debug跟过来,到了ClassLoaderContextSelector,这里入参configLocation为null
protected LoggerContext createContext(final String name, final URI configLocation) {
	// 3. 创建默认的LoggerContext,
  	return new LoggerContext(name, null, configLocation);
}
// LoggerContext,构造方法很简单,不看了,主要看实例化时初始化的一些变量以及一些静态变量
// 这个就是默认配置啦,每个LoggerContext被创建之初都会绑定默认配置,在reconfig方法中进行修改
private volatile Configuration configuration = new DefaultConfiguration();

// 题外话:在LoggerContext执行stop方法时,用于替代当前的配置文件,然后执行Log4J的收尾工作。好处是避免在收尾工作时,还有程序打印日志而报错
private static final Configuration NULL_CONFIGURATION = new NullConfiguration();
// 空配置,其实就是一个空壳,参考文章https://blog.youkuaiyun.com/sweetyi/article/details/105147571
public NullConfiguration() {
    super(null, ConfigurationSource.NULL_SOURCE);
    setName(NULL_NAME);
    final LoggerConfig root = getRootLogger();
    // 停止日志输出
    root.setLevel(Level.OFF);
}

以上就是LoggerContext的获取步骤,获取完之后执行start方法

public void start() {
     // ***************略去了许多代码*****************
        if (this.isInitialized() || this.isStopped()) { 
            reconfigure(); 
        }
     LOGGER.debug("LoggerContext[name={}, {}] started OK.", getName(), this);
}

// 这里的后续步骤其实就是去找配置,然后重新设置configuration    
 private void reconfigure(final URI configURI) {
      final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null;
      final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl);
      if (instance == null) {
          LOGGER.error("Reconfiguration failed: No configuration found for '{}' at '{}' in '{}'", contextName, configURI, cl);
      } else {
      	  // 这个方法也还挺多操作的,下面简单看一下
          setConfiguration(instance);
      }
}

分析一下获取Configuration部分的代码

// ConfigurationFactory源码,部分代码略,这个部分之前文章简单分析过,这里不再赘述
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();
        for (final String suffix : types) {
            configName = named ? prefix + name + suffix : prefix + suffix; 
            final ConfigurationSource source = ConfigurationSource.fromResource(configName, loader);
            if (source != null) {
            	// 找到了配置,然后主要看下这里做了什么(这里factory的实现以XmlConfigurationFactory为例)
                return factory.getConfiguration(loggerContext, source);
            }
        }
    }
    return null;
}

public Configuration getConfiguration(final LoggerContext loggerContext, final ConfigurationSource source) {
    return new XmlConfiguration(loggerContext, source);
}

public XmlConfiguration(final LoggerContext loggerContext, final ConfigurationSource configSource) {
    super(loggerContext, configSource);
    final File configFile = configSource.getFile();
    // 略去中间一部分解析xml文件的代码
    rootElement = document.getDocumentElement();
    final Map<String, String> attrs = processAttributes(rootNode, rootElement);
    final StatusConfiguration statusConfig = new StatusConfiguration().withVerboseClasses(VERBOSE_CLASSES)
            .withStatus(getDefaultStatus());
    int monitorIntervalSeconds = 0;
    for (final Map.Entry<String, String> entry : attrs.entrySet()) {
        final String key = entry.getKey();
        final String value = getStrSubstitutor().replace(entry.getValue());
        if ("status".equalsIgnoreCase(key)) {    // 指定log4j的内部StatusLogger的日志级别
            statusConfig.withStatus(value);
        } 
        // 略去中间一堆我不太了解的字段
        else if ("monitorInterval".equalsIgnoreCase(key)) {  // 配置监听的时间设置
            monitorIntervalSeconds = Integer.parseInt(value);
        } else if ("advertiser".equalsIgnoreCase(key)) {
            createAdvertiser(value, configSource, buffer, "text/xml");
        }
    }
        initializeWatchers(this, configSource, monitorIntervalSeconds); // 初始化配置监听
        statusConfig.initialize();
    } catch (final SAXException | IOException | ParserConfigurationException e) {
        LOGGER.error("Error parsing " + configSource.getLocation(), e);
    }
	// 略,懒得看了,不是重点
}

获取到之后,重新设置configuration,之前该值是默认配置

public Configuration setConfiguration(final Configuration config) {
        configLock.lock();
        try {
            final Configuration prev = this.configuration;
			// ********略***************
			// 这里就是根据配置文件去生成记录appenders,loggerConfigs(即Loggers)
            config.start();
            this.configuration = config;
            // 根据新的配置文件去更新logger,这里因为之前是默认配置,不存在logger,所以实际并不会更新
            updateLoggers();
            if (prev != null) {
                prev.removeListener(this);
                prev.stop();
            }
            return prev;
        } finally {
            configLock.unlock();
        }
    }

// 截取一部分代码
else if (child.getName().equalsIgnoreCase("Appenders")) {
   appenders = child.getObject();
} else if (child.getName().equalsIgnoreCase("Loggers")) {
   final Loggers l = child.getObject();
   loggerConfigs = l.getMap();
   setLoggers = true;
   if (l.getRoot() != null) {
       root = l.getRoot();
       setRoot = true;
}
               

附上官方文档关于Configuration的描述:
每一个LoggerContext都有一个活跃的Configuration。这个Configuration包含所有的Appender、上下文范围的Filter、LoggerConfig以及StrSubstitutor的引用。当重新配置时,将会有两个Configuration对象存在。一旦所有的Logger都已经被导向到新的Configuration上时,旧的Configuration就会被停止且丢弃。
以上就是LoggerContext准备就绪,开始获取Logger了

// LoggerContext
public Logger getLogger(final String name, final MessageFactory messageFactory) {
    // 先检查是否已存在
    Logger logger = loggerRegistry.getLogger(name, messageFactory);
    if (logger != null) {
        AbstractLogger.checkMessageFactory(logger, messageFactory);
        return logger;
    }
	// 不存在则创建,并记录保持下来
    logger = newInstance(this, name, messageFactory);
    loggerRegistry.putIfAbsent(name, messageFactory, logger);
    return loggerRegistry.getLogger(name, messageFactory);
}

protected Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) {
    return new Logger(ctx, name, messageFactory);
}

下面就是创建的过程

// Logger
protected Logger(final LoggerContext context, final String name, final MessageFactory messageFactory) {
    super(name, messageFactory);
    this.context = context;
    privateConfig = new PrivateConfig(context.getConfiguration(), this);
}

/**
 * 这里再看一下LoggerContext的getConfiguration方法,注释也说明了很多东西
 * Returns the current Configuration. The Configuration will be replaced when a reconfigure occurs.
 *
 * @return The current Configuration, never {@code null}, but may be
 * {@link org.apache.logging.log4j.core.config.NullConfiguration}.
 */
public Configuration getConfiguration() {
	return configuration;
}

public PrivateConfig(final Configuration config, final Logger logger) {
    this.config = config;
    // 看这里,可以看出整个配置中,最重要的属性就是loggerConfig 
    this.loggerConfig = config.getLoggerConfig(getName());
    this.loggerConfigLevel = this.loggerConfig.getLevel();
    this.intLevel = this.loggerConfigLevel.intLevel();
    this.logger = logger;
}

public LoggerConfig getLoggerConfig(final String loggerName) {
	// 这就是核心了,终于到这了
	// 先直接找有没有这个对应名称的LoggerConfig
    LoggerConfig loggerConfig = loggerConfigs.get(loggerName);
    if (loggerConfig != null) {
        return loggerConfig;
    }
    // 如果没有,就按照报名结构对入参loggerName进行拆分,找是否有符合的父类LoggerConfig
    String substr = loggerName;
    while ((substr = NameUtil.getSubName(substr)) != null) {
        loggerConfig = loggerConfigs.get(substr);
        if (loggerConfig != null) {
            return loggerConfig;
        }
    }
    // 都找不到,那么就返回root loogerConfig
    return root;
}

Logger创建完毕,附上官方文档关于Logger的描述:
Logger本身并不做转向的动作。它只是有一个名字并且和LoggerConfig关联。它继承了AbstractLogger并且实现了所需的方法。当配置被修改时,Logger可能变为与一个不同的LoggerConfig关联,这样会导致他们的表现被改变。
至此,分析完毕。

简单总结一下:

  1. 找到合适的LoggerContextFactory,创建一个新的LoggerContext,此时configuration属性为初始默认配置
  2. LoggerContext启动start,并进行重新配置reconfig,查找合适的配置文件,解析生成新的Configuration
  3. 新的Configuration启动start,通过配置文件加载appender,loggerConfigs等等。同时处理旧的默认配置
  4. 上述3点完成后,LoggerContext就算是处理完毕了,然后通过它获取Logger

常规配置文件加载logger模式下,1个LoggerContext包含一个1个实时有效的Configuration,1个Configuration(对应配置文件)记录了多个LoggerConfig信息,通过LoggerContext创建的Logger,1个Logger记录了一个Configuration,但是根据Logger的name从Configuration中仅获取一个LoggerConfig。

附上官方文档中的一段话:
应用程序要使用Log4j 2的API,需要从LogManager中获取一个有明确名称的Logger。LogManager将会定位到一个合适的LoggerContext并且从中获取Logger。如果Logger必须被创建,那么它会和包含这些信息的LogConfig相关联:a)与Logger相同的名称;b)父包的名称;c)根LoggerConfig。LoggerConfig对象根据配置中的Logger声明而创建。LoggerConfig与实际处理LogEvent事件的Appender关联。

11、CUDA 内存优化:平铺矩阵乘法技术解析 本文深入解析了CUDA中的平铺矩阵乘法技术,重点介绍了如何利用共享内存和线程协作减少全局内存访问,提升计算效率。通过矩阵乘法实例,详细阐述了平铺算法的执行流程、内核代码实现及性能优化策略,包括平铺大小选择、线程同步机制和代码优化建议。文章还分析了该技术在深度学习、图像处理和科学计算等领域的应用价值,为CUDA程序的内存优化提供了系统性指导。 阅读详情

相关推荐

NHANES数据库实战:数据合并与加权分析技巧

本文详细解析了NHANES数据库实战中的核心技巧,重点阐述了数据合并与加权分析的正确方法。通过两个具体案例,手把手指导如何从数据下载、合并、权重计算到使用R语言survey包进行加权统计分析,避免因忽略复杂抽样设计而导致的研究偏倚,确保分析结果的准确性与可发表性。

weixin_29057065的博客 585

log4j - Logger.getLogger(Class) 参数作用

在项目中使用Log4J并不是一件困难的事情,简单粗暴的方式就是在每个类A中声明一个Logger私有属性 [html] view plain copy private static Logger logger = Logger.getLogger(A.class);   这样虽然简单,但是带来有两个问题:  1.增加系统开销

永远的北极光 2万+

OTP语音芯片SOP8的前世今生_如九齐_硕呈_钰绅等以及国产方案KT148A

语音芯片ic的其中一个品类,就是SOP8封装的OTP语音芯片,非常的经典和常用。源头的供应商基本都是台系的原厂,比如:九齐、硕呈、佑华等等,其中佑华就算是鼻祖了,早期的4位机也是在语音市场得到了升华。 OTP(One Time Programmable)是单片机的一种存储器类型,意思是一次性可编程:程序烧入单片机后,将不可再次更改和清除。

qyvhome的博客 1873

log4j| log4j-日志方法

Logger类提供了多种方法来处理日志记录活动。Logger类不允许我们实例化新的Logger实例,但是它提供了两种用于获取Logger对象的静态方法: public static Logger getRootLogger(); public static Logger getLogger(String name); 这两个方法中的第一个返回应用程序实例的根记录器,并且它没有名称。 通过传递记...

YvesHe的专栏 537

Python+Appium实现泛微OA自动打卡:5分钟搭建移动端自动化脚本

移动端自动化测试是软件测试与办公自动化领域的重要技术方向,其核心原理是通过程序模拟用户对手机应用界面的操作,实现重复性任务的自动执行。Appium作为主流的开源移动端自动化框架,基于WebDriver协议,支持跨平台且无需修改被测应用,为自动化脚本开发提供了标准化接口。在工程实践中,结合Python简洁的语法和丰富的生态,可以快速构建稳定可靠的自动化解决方案。这一技术组合的价值在于能够高效处理“重复性、低价值、高频率”的日常操作,例如考勤打卡、数据填报等办公场景,显著提升工作效率。本文以泛微OA Emobi

weixin_28836875的博客 391

AUTOSAR E2E Protocol实战:Profile1到Profile5的配置差异与最佳实践

本文深入解析AUTOSAR E2E Protocol中Profile1到Profile5的核心配置差异与适用场景。针对经典CAN、CAN FD及以太网等不同总线,详细对比了计数器、CRC、DataID等关键参数,并结合实战代码与配置示例,为工程师根据功能安全等级、数据长度与带宽限制选择最佳Profile提供了清晰的选型路径与工程实践指南。

milk5的博客 945

org.apache.log4j.Logger详解

​ 在强调可重用组件开发的今天,除了自己从头到尾开发一个可重用的日志操作类外, Apache 为我们提供了一个强有力的日志操作包 -Log4j。Log4j 是 Apache 的一个开放源代码项目,通过使用 Log4j ,我们可以控制日志信息输送的目的地是控制台、文件、 GUI 组件、甚至是套接口服 务器、 NT 的事件记录器、 UNIX Syslog 守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。

qq_43842093的博客 2340

COMSOL实战:薄膜声学超材料模态分析全流程解析(含预应力设置技巧)

本文详细解析了使用COMSOL进行薄膜声学超材料模态分析的全流程,包括预应力设置技巧和共振频率优化方法。通过实际案例和参数设置指南,帮助工程师掌握从几何建模到结果解读的关键步骤,特别适合声学超材料和共振薄膜结构的设计与优化。

ujm5678901的博客 293

Log4j2学习记录

Log4j2学习日志门面和实现运用1.获取logger1.1.getLogger()调用流程1.2.格式化输出1.3.LogBuilder2.配置文件 日志门面和实现 三种门面:jcl(commons logging)、slf4j、log4j-api 具体实现和桥接关系如下图 log4j2的api和实现 运用 1.获取logger getLogger()方法可接受不同参数,参数最终定义为该logger的名称,与配置文件中<logger/>标签对应 LogManager.getLogger(

weixin_44521586的博客 1307

从传感器到执行-智能家居 Agent 的感知-决策-执行闭环

本文提出了一种面向智能家居的感知型Agent架构,通过"感知-决策-执行"的闭环系统实现智能化控制。感知模块整合多源传感器数据,决策模块基于规则或机器学习模型生成控制策略,执行模块完成设备操作。系统能够实时监测环境参数和用户状态,自动调节温度、照明等设备,提升家居舒适度。该架构可扩展为多模态感知与强化学习相结合的智能系统,为智慧家居发展提供技术基础。

一键难忘的博客 1123

信贷系统学习总结(6)—— 贷前、贷中、贷后全流程核心模型解析

本文系统解析了金融风控模型的技术演进与应用实践。从贷前、贷中到贷后全流程,详细介绍了A卡、B卡、C卡三类核心评分模型,以及反欺诈、动态监控、催收优化等关键技术的实现路径。重点阐述了特征工程设计、模型验证指标、联邦学习等创新应用,并提供了多个实战案例数据。同时提出了算法选择的"黄金三角"原则和分阶段技术演进路线,强调数据治理、模型全生命周期管理和复合型团队建设的重要性。文章指出未来风控将向决策智能化、数据无感化和风险预知化方向发展,需要平衡技术创新与合规要求。

科技D人生 1222

Java日志管理:Logger.getLogger()…

第一、Logger.getLogger()和LogFactory.getLog()的区别    1.Logger.getLogger()是使用log4j的方式记录日志;     2.LogFactory.getLog()则来自apache的common-logging包。 common-logging组件:        Jakarta Commons Logging (JCL)提供的是一个日志(

6453

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Log4j源码阅读之一—Logger的获取

本次Log4j源码研读的入口,是从 logger = Logger.getLogger("test"),这个方法调用开始,我们看看下边是时序图: 下边是对上述时序图的解读: 我们actioner通过调用Logger.getLogger("test")方法的时候,会提交的Logger类的静态方法getLogger,这个静态方法源码如下:  public static Logger ge

plkkoko的专栏 2777

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

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

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

log4j2(三) 如何通过类名获取到logger呢?logger与loggerConfig是什么关系?-源码解析

文章目录情景解析从例子说起从LoggerFactory获取logger从LoggerContext中获取logger创建Logger真正的主角LoggerConfig获取LoggerConfig流程图验证小结 情景 之所以想写这篇文章是因为经常看到一些相关联的问题: 怎么有这么多非本项目的log出现? 譬如引入了其他的sdk,他们又很无节操的打了很多日志。 怎么去除不必要的包的日志? 为什么lo...

sweetyi的专栏 4044

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

请解释Log4j是什么?它在Java开发中的作用是什么?请列出Log4j中可用的主要Appender,并解释它们各自的作用。你如何在代码中获取并使用Log4j的Logger实例?

在配置Log4j时,可以根据项目的需求选择合适的Appender,并设置相应的参数来控制日志的输出方式和行为。此外,Log4j的配置非常灵活,开发人员可以通过一个外部的配置文件来定义日志记录的方式和级别,而不需要修改应用程序的代码。日志输出目标配置:Log4j允许开发人员将日志信息输出到不同的目标,如控制台、文件、数据库等。总的来说,Log4j在Java开发中起到了记录日志、控制日志级别和输出目标的作用,帮助开发人员更好地管理和理解应用程序的运行状态。作用:每天滚动日志文件,即每天生成一个新的日志文件。

Aaron的博客 564

log4j2 logger_简单一致的Log4j2 Logger命名

log4j2 logger 在“ 带有Java 7方法句柄的可移植记录器名称”一文中 ,我写了关于使用Java 7的方法句柄来命名类的记录器的文章。 我在那篇文章中说过,这种方法的优点包括记录器命名的一致性,并避免了意外的代码复制和粘贴,这可能导致不同的类名被用作记录器名称。 在这篇文章中,我看看如何Log4j的2提供了一种方法实现这些同样的好处。 Log4j 2可以识别基于类名的记录器命...

最佳 Java 编程 1023

java 把log4j封装成utils_log4j的终极封装

packagecom.ycl.core.common;importjava.util.HashMap;importjava.util.Map;importorg.apache.log4j.Logger;public classLog {private static Map loggerMap = new HashMap();public static void main(String[] args...

weixin_42376799的博客 311

log4j Logger方法

Logger类提供了多种方法来处理日志活动。 Logger类不允许实例化一个新的记录器实例,但它提供了两个静态方法获得一个 Logger 对象: public static Logger getRootLogger(); public static Logger getLogger(String name); 此处两种方法的第一个返回应用程序实例根记录器并没有名字。任何其

jQuerys的专栏 836

log4j创建Logger实例解读

log4j创建Logger实例解读API:https://logging.apache.org/log4j/1.2/apidocs/一些对该方面源码的解读http://blog.youkuaiyun.com/wanglz666/article/details/43195149http://www.blogjava.net/DLevin/archive/2012/07/10/382678.htmlhttp://w

zwt0909的博客 3618

log4j 使用示例

1.配置默认的 logger :rootLogger#config root logger, this is the default loggerlog4j.rootLogger = DEBUG,stdout,rolling_file# Console Appender #log4j.appender.stdout = org.apache.log4j.ConsoleAppenderlog4j.a...

彻底拆分,一切可控! 988

【Spring】在springmvc中使用log4j日志功能

在springmvc框架中使用log4j日志功能

吃货小跟班的博客 2387

log4j(一)——什么是Log4j以及Log4j的体系结构

一、什么是log4j

野犬17的博客 5696

Log4j Logger方法

Logger类提供了多种方法来处理日志活动。 Logger类不允许实例化一个新的记录器实例,但它提供了两个静态方法获得一个 Logger 对象: public static Logger getRootLogger(); public static Logger getLogger(String name) 此处两种方法的第一个返回应用程序实例根记录器并没有名字。任何其他命名的...

qq_37031892的博客 1731

log4j.rootLogger 与log4j.rootCategory 有什么区别

下面是在log4j官方的API中写的,足以能解释logger与category的区别。。。public class Categoryextends java.lang.Objectimplements AppenderAttachableThis class has been deprecated and replaced by the Logger subclass. It

This is my house! 9335

java main方法 log4j,Log4J日志方法

Logger类具有多种方法来处理日志记录活动。 Logger类不允许我们实例化新的Logger实例, 但是它支持两种用于获取Logger对象的静态方法-public static Logger getRootLogger();public static Logger getLogger(String name);这两个方法中的第一个返回应用程序实例的根记录器, 并且它没有名称。第二种方法通过传递记...

weixin_42116734的博客 991

log4j默认配置

import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class LogTest { public static void main(String[] a) { Logger logger = LoggerFactory.getLogger(String.class); // Logger logger = LogManager.getLogger(); logger.erro

Mr_moving 1615
上一篇: log4j默认配置
下一篇: log4j2之filter
MrMoving
博客等级 码龄10年 54粉丝 145原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值