java log4j2消息来自Spring MessageSource等文件

dm7nw8vv  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(110)

我在Java 1.8下使用log4j 2 2.20.0和spring-boot 1.5.8,我特灵简化我的软件从bloatcode。为了记录消息,我目前使用这种方式:

#message.properties
message-1=Current time is {0}
message-2=Message for supplier at {0}

@Configuration
public class BeanDefinition {
    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("messages.poc");
        return messageSource;
    }

    @Bean
    public MessageSourceAccessor getMessageFormatAccessor(MessageSource messageSource) {
        return new MessageSourceAccessor(messageSource);
    }
}

@Component
@Log4j2
public class MessageSourceAccessorRunner implements ApplicationRunner {
    @Autowired
    private MessageSourceAccessor accessor;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Object[] logArgs = {Instant.now()};
        log.info(accessor.getMessage("message-1", logArgs));
    }
}

我正在尝试做的是执行这样的事情,以保存我的代码从大量的bloatcode:

log.debug("message-2", logArgs);

其效果与

log.debug(() -> accessor.getMessage("message-2", logArgs));

意思是如果日志记录级别是DEBUG级别,则记录构造的消息,以保存性能。
有人能帮我解决这个问题吗?谢谢!

jaxagkaj

jaxagkaj1#

Log4j 2.x如何解释日志调用的(String, Object...)参数是由日志记录器使用的MessageFactory决定的。
当你创建一个日志记录器时,你可以将MessageFactory作为第二个参数传递给LogManager#getLogger调用(例如LogManager#getLogger(Class<?>, MessageFactory)
要使用MessageSource化消息,您需要创建:

public class MessageSourceMessage implements Message {

    private final MessageSource source;
    private final String code;
    private final Object[] args;

    public MessageSourceMessage(MessageSource source, String code, Object[] args) {
        this.source = source;
        this.code = code;
        this.args = args;
    }

    @Override
    public String getFormattedMessage() {
        return source.getMessage(code, args, Locale.getDefault());
    }

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

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

    @Override
    public Throwable getThrowable() {
        return null;
    }
}
  • 以及匹配的消息工厂:
public class MessageSourceMessageFactory extends AbstractMessageFactory {

    private final MessageSource source;

    public MessageSourceMessageFactory(MessageSource source) {
        this.source = source;
    }

    @Override
    public Message newMessage(CharSequence message) {
        return new MessageSourceMessage(source, message.toString(), null);
    }

    @Override
    public Message newMessage(String message) {
        return new MessageSourceMessage(source, message, null);
    }

    @Override
    public Message newMessage(String message, Object... params) {
        return new MessageSourceMessage(source, message, params);
    }
}
  • 然后你可以使用消息工厂来示例化你的记录器:
Logger logger = LogManager.getLogger(Example.class,
                                     new MessageSourceMessageFactory(source));

上面的例子有一些缺点:

  • 由于“code”没有提供有关参数数量的信息,因此如果“code”解析为“Hello {0} and {1}",则类似
logger.info("code", param0, param1, throwable);

将丢弃throwable参数,而不是将其用作消息的throwable。您可以考虑在代码中编码参数的数量,以便MessageSourceMessage可以将第一个附加参数用作throwable。

  • 这个messagefactory生成临时对象。2你可以考虑实现ReusableMessage,这样大多数时候都会使用同一个message示例。

相关问题