You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Log4j2结合Spring MessageSource简化日志代码实现求助

解决方案

要实现log.debug("message-2", logArgs)这种简化写法,同时保留延迟加载消息的性能优势,我们可以通过扩展Log4j2的消息处理机制,结合Spring的MessageSourceAccessor来实现。

步骤1:创建MessageSourceAccessor静态持有类

由于自定义的Log4j2消息需要访问Spring管理的MessageSourceAccessor,我们用一个静态Holder类来持有它,确保Spring启动时完成注入:

import org.springframework.context.MessageSourceAccessor;
import org.springframework.stereotype.Component;

@Component
public class MessageSourceAccessorHolder {
    public static MessageSourceAccessor accessor;

    @Autowired
    public void setAccessor(MessageSourceAccessor accessor) {
        MessageSourceAccessorHolder.accessor = accessor;
    }
}

步骤2:实现自定义Log4j2 Message类

这个类会延迟构造本地化消息,仅当日志级别满足时才调用MessageSourceAccessor获取消息内容:

import org.apache.logging.log4j.message.Message;

public class LocalizedMessage implements Message {
    private final String messageKey;
    private final Object[] args;
    private String formattedMessage;

    public LocalizedMessage(String messageKey, Object[] args) {
        this.messageKey = messageKey;
        this.args = args;
    }

    @Override
    public String getFormattedMessage() {
        if (formattedMessage == null) {
            // 延迟加载:仅当需要输出日志时才构造消息
            formattedMessage = MessageSourceAccessorHolder.accessor.getMessage(messageKey, args);
        }
        return formattedMessage;
    }

    @Override
    public String getFormat() {
        return messageKey;
    }

    @Override
    public Object[] getParameters() {
        return args;
    }

    @Override
    public Throwable getThrowable() {
        return null;
    }

    @Override
    public void formatTo(StringBuilder buffer) {
        buffer.append(getFormattedMessage());
    }
}

步骤3:实现自定义MessageFactory

这个工厂类负责创建我们的LocalizedMessage实例,替代Log4j2默认的消息处理:

import org.apache.logging.log4j.message.AbstractMessageFactory;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.ParameterizedMessage;

public class LocalizedMessageFactory extends AbstractMessageFactory {
    @Override
    public Message newMessage(String messageKey, Object... args) {
        // 可选:区分本地化消息和普通参数化消息
        // 如果消息包含{},则使用默认的参数化消息处理
        if (messageKey.contains("{}")) {
            return new ParameterizedMessage(messageKey, args);
        }
        // 否则当作本地化消息键处理
        return new LocalizedMessage(messageKey, args);
    }

    // 重载基础方法以支持不同参数数量的调用
    @Override
    public Message newMessage(String messageKey, Object p0) {
        return newMessage(messageKey, new Object[]{p0});
    }

    @Override
    public Message newMessage(String messageKey, Object p0, Object p1) {
        return newMessage(messageKey, new Object[]{p0, p1});
    }
}

步骤4:配置Log4j2使用自定义MessageFactory

有两种方式让Log4j2使用我们的工厂:

方式A:通过Lombok配置自动生成(推荐)

在项目根目录创建lombok.config文件,添加以下内容,让Lombok的@Log4j2注解自动使用自定义工厂:

lombok.log.log4j2.messageFactory=com.yourpackage.LocalizedMessageFactory

替换com.yourpackage为你实际的包路径。

方式B:手动创建Logger实例

如果不想修改Lombok配置,可以在每个类中手动创建Logger:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

@Component
public class MessageSourceAccessorRunner implements ApplicationRunner {
    private static final Logger log = LogManager.getLogger(MessageSourceAccessorRunner.class, new LocalizedMessageFactory());

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Object[] logArgs = {Instant.now()};
        // 现在可以直接用简化写法,性能和Supplier方式一致
        log.debug("message-2", logArgs);
    }
}

关键说明

  • 延迟加载机制:Log4j2会先判断日志级别是否允许输出,只有当级别满足时才会调用getFormattedMessage()方法,此时才会触发MessageSourceAccessor的消息构造逻辑,完全等价于log.debug(() -> accessor.getMessage("message-2", logArgs))的性能效果。
  • 兼容普通消息:如果需要使用Log4j2默认的参数化消息(如log.info("Hello {}", name)),可以在LocalizedMessageFactory的newMessage方法中通过判断消息是否包含{}来切换处理逻辑,确保两种消息格式都能正常使用。

内容的提问来源于stack exchange,提问作者Stefano Riffaldi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 21:12:51