🌐
Spring
docs.spring.io › spring-boot › docs › current-SNAPSHOT › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 4.0.1 API)
@FunctionalInterface public interface DeferredLogFactory · Factory that can be used to create multiple DeferredLog instances that will switch over when appropriate. Since: 2.4.0 · Author: Phillip Webb · See Also: DeferredLogs · All MethodsInstance MethodsAbstract MethodsDefault Methods ...
🌐
Spring
docs.spring.io › spring-boot › docs › 2.4.3 › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 2.4.3 API)
1 month ago - org.springframework.boot.logging · All Known Implementing Classes: DeferredLogs · Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface DeferredLogFactory ·
🌐
Spring
docs.enterprise.spring.io › spring-boot › docs › 2.7.25 › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 2.7.25 API)
org.springframework.boot.logging · All Known Implementing Classes: DeferredLogs · Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface DeferredLogFactory ·
🌐
Spring
docs.spring.io › spring-boot › docs › 2.4.13 › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 2.4.13 API)
org.springframework.boot.logging · All Known Implementing Classes: DeferredLogs · Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface DeferredLogFactory ·
🌐
Spring
docs.spring.io › spring-boot › api › java › org › springframework › boot › logging › DeferredLogs.html
DeferredLogs (Spring Boot 3.5.5 API)
org.springframework.boot.logging.DeferredLogs · All Implemented Interfaces: DeferredLogFactory · public class DeferredLogs extends Object implements DeferredLogFactory · A DeferredLogFactory implementation that manages a collection DeferredLog instances. Since: 2.4.0 ·
🌐
Spring
docs.spring.io › spring-boot › docs › 3.0.x › api › org › springframework › boot › logging › DeferredLogs.html
DeferredLogs (Spring Boot 3.0.13 API)
org.springframework.boot.logging.DeferredLogs · All Implemented Interfaces: DeferredLogFactory · public class DeferredLogs extends Object implements DeferredLogFactory · A DeferredLogFactory implementation that manages a collection DeferredLog instances. Since: 2.4.0 ·
🌐
JDriven
jdriven.com › blog › 2025 › 02 › Spring-Sweets-Use-Logging-in-EnvironmentPostProcessor-Implementation
Spring Sweets: Use Logging in EnvironmentPostProcessor Implementation - JDriven Blog
February 10, 2025 - By using the Log instances created from DeferredLogFactory Spring Boot will make sure the log messages are written when the logging system is initialized. In the following example you can see how to use the DeferredLogFactory: package mrhaki.sample; import org.apache.commons.logging.Log; import ...
Find elsewhere
Top answer
1 of 5
13

The problem here is that logging system initialized only after spring context is initialized. When the log method is invoked the log system does not know what to do with the information and it does nothing.

There is no elegant way to solve this issue. You either get rid of spring-managed log system or use deferred log mechanisms (just like spring does internally).

To be able to use DeferredLog you have to make sure that after context initialization the system will request to replay logs.

Here is one of the ways how it could be achieved:

@Component
public class MyEnvironmentPostProcessor implements
        EnvironmentPostProcessor, ApplicationListener<ApplicationEvent> {

    private static final DeferredLog log = new DeferredLog();

    @Override
    public void postProcessEnvironment(
            ConfigurableEnvironment env, SpringApplication app) {
        log.error("This should be printed");
    }

    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        log.replayTo(MyEnvironmentPostProcessor.class);
    }
}

In this example every log message is cached in the DeferredLog. And once the context initialized the system will call onApplicationEvent. This method will replay all the cached log-events to the standard logger.

NOTE: I used ApplicationListener here but you can use every convenient way. The idea is to call DeferredLog.replayTo() once context initialized and it does not matter from which place you call it.

PS: The location of spring.factories should be src/main/resources/META-INF otherwise postProcessEnvironment might not be invoked.

2 of 5
9

As noted in the accepted answer, the problem is the logging system isn't initialized yet when EnvironmentPostProcessors are run.

However, using a mechanism like a static DeferredLog in EnvironmentPostProcessor to store the logs temporarily, then replay them in a ApplicationListener<ApplicationPreparedEvent> (once the logging system is initialized) does not work either because the EnvironmentPostProcessor and ApplicationListener are loaded and initialized by different class loaders.

Because of that, the instance of the Class used for the ApplicationListener has no visibility into the instance of the Class used as the EnvironmentPostProcessor (even if they are in fact the same class).

One hack would be to use System.setProperty(...) to set what you want to log out in the EnvironmentPostProcessor, and System.getProperty(...) in the ApplicationListener to log it out. This avoids the issue with Spring's class loaders. I definitely recommend against using this approach, but it does work.

YMMV, but in my case I found that moving the custom environment setup logic from an EnvironmentPostProcessor to an ApplicationListener<ApplicationPreparedEvent> worked just fine for me, logging included.

Spring Application Events reference: https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/reference/html/spring-boot-features.html#boot-features-application-events-and-listeners


UPDATE: Based on shaohua-shi's answer, here is a simple working solution that uses an ApplicationContextInitializer to replay a DeferredLog after the logging system has been initialized:

public class MyEnvPostProcessor implements EnvironmentPostProcessor {

    private DeferredLog log = new DeferredLog();

    @Override
    public void postProcessEnvironment(ConfigurableEnvironment env, SpringApplication app) {
        app.addInitializers(ctx -> log.replayTo(MyEnvPostProcessor.class));

        log.warn("In Env Post Processor");
    }
}

Log:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.1.RELEASE)

2020-06-25 20:51:15.118  WARN 7297 --- [  restartedMain] c.e.testenvpostproc.MyEnvPostProcessor   : In Env Post Processor
🌐
Vmware
docs.spring.vmware.com › spring-boot › docs › 3.0.19.1 › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 3.0.19.1 API)
Package org.springframework.boot.logging · All Known Implementing Classes: DeferredLogs · Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface DeferredLogFactory ·
🌐
Vmware
docs.spring.vmware.com › spring-boot › docs › 3.0.15 › api › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (Spring Boot 3.0.15 API)
Package org.springframework.boot.logging · All Known Implementing Classes: DeferredLogs · Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference. @FunctionalInterface public interface DeferredLogFactory ·
🌐
Jar-Download
jar-download.com › home › org.springframework.boot › spring-boot › 2.5.5 › source code › deferredlogfactory.java
org.springframework.boot.logging.DeferredLogFactory Maven / Gradle / Ivy
October 13, 2023 - */ package org.springframework.boot.logging; import java.util.function.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Factory that can be used to create multiple {@link DeferredLog} instances that will * switch over when appropriate. * * @author Phillip Webb * @since 2.4.0 * @see DeferredLogs */ @FunctionalInterface public interface DeferredLogFactory { /** * Create a new {@link DeferredLog} for the given destination.
🌐
Spring
docs.spring.io › spring-boot › docs › current › api › org › springframework › boot › logging › package-summary.html
org.springframework.boot.logging (Spring Boot 4.0.3 API)
December 22, 2023 - Deferred Log that can be used to store messages that shouldn't be written until the logging system is fully initialized. ... Factory that can be used to create multiple DeferredLog instances that will switch over when appropriate. ... A DeferredLogFactory implementation that manages a collection ...
🌐
Javadoc.io
javadoc.io › static › org.springframework.boot › spring-boot › 2.6.6 › org › springframework › boot › logging › DeferredLogs.html
DeferredLogs (spring-boot 2.6.6 API)
org.springframework.boot.logging.DeferredLogs · All Implemented Interfaces: DeferredLogFactory · public class DeferredLogs extends java.lang.Object implements DeferredLogFactory · A DeferredLogFactory implementation that manages a collection DeferredLog instances.
🌐
Docshoster
docshoster.org › p › spring-projects › spring-boot › 2.6.9 › org › springframework › boot › logging › DeferredLogFactory.html
DeferredLogFactory (spring-boot 2.6.9) - DocsHoster
November 25, 2025 - @FunctionalInterface public interface DeferredLogFactory · Factory that can be used to create multiple DeferredLog instances that will switch over when appropriate. ... Create a new DeferredLog for the given destination. ... Create a new DeferredLog for the given destination.
🌐
Spring
docs.spring.io › spring-boot › › api › kotlin › spring-boot-project › spring-boot › org.springframework.boot.logging › index.html
org.springframework.boot.logging
July 31, 2025 - Deferred Log that can be used to store messages that shouldn't be written until the logging system is fully initialized. ... Factory that can be used to create multiple DeferredLog instances that will switch over when appropriate. ... A DeferredLogFactory implementation that manages a collection ...