Spring @PreDestroy results in random registration rather than registration

I am using Spring, and upon completion I have @PreDestroy cleaning beans. I don’t understand why logging accidentally happens sometimes, and others fail.

// Using Log4j2
Logger log = LogManager.getLogger(MyClass.class);

@PreDestroy
public void close() {
    log.warn("Test");
}

Sometimes I get nothing (no "Test" is registered), in other cases I get:

[13:48:44] INFO  MyClass: Test

If I include System.out.println("Is this run?");close () in the method, it will always print.

I'm not sure what is going on. I don’t know if this is because the JVM is shutting down and the log is dead ... but I thought it would throw some sort of exception?

Please note that the log is logged as a + stdout file, I don’t know if this will affect anything. Logging works fine for the other thousands of thousands of lines of code, but not for this.

. , .

EDIT: MyClass bean spring.xml.

+4
3

, , Runtime.addShutdownHook:

, .

, , LogManager Spring IOC JVM shutdown, , . LogManager , . IOC, .

JEE, , .

, , shutdownHook="disable" Log4j 2 <configuration>. Log4j 2 . ctx.registerShutdownHook() ( IOC) . - :

class MyShutdownHook extends Thread {
    private AbstractApplicationContext ctx;
    public MyShutdownHook(AbstractApplicationContext ctx) {
        this.ctx = ctx;
    }
    public void run() {
        ctx.close();
        Set<LoggerContext> contexts = new HashSet<>();
        for (Logger logger : LoggerContext.getLoggers()) {
            contexts.add(logger.getContext());
        }
        for (LoggerContext ctx : contexts) {
            Configurator.shutdown(LogManager.getContext());
        }
    }
}

AbstractApplicationContext ctx = /* create context */
Runtime.getRunTime().addShutdownHook(new MyShutdownHook(ctx);

: Log4j2.
Caveat: , , , API.

+4

, , :

JavaEE API javadoc:

  • , non-interceptor, : void()
  • , PreDestroy, , , .
  • .
  • .
  • , , , EJB, EJB .

, - "", .

+1

Just like @Devon_C_Miller answer, but updated to reflect the latest version of log4j2

public class MonolithApplication {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.refresh();
    Runtime.getRuntime().addShutdownHook(new Log4j2AwareShutdownHook(context));
  }
}

class Log4j2AwareShutdownHook extends Thread {
  private AbstractApplicationContext ctx;
  Log4j2AwareShutdownHook(AbstractApplicationContext ctx) {
    this.ctx = ctx;
  }
  public void run() {
    ctx.close();
    LogManager.shutdown();
  }
}

and in log4j2 configuration

<?xml version="1.0" encoding="UTF-8"?>
<Configuration shutdownHook="disable">
    <Properties>
        <Property name="LOG_EXCEPTION_CONVERSION_WORD">%xEx</Property>
        <Property name="LOG_LEVEL_PATTERN">%5p</Property>
        <Property name="LOG_DATEFORMAT_PATTERN">yyyy-MM-dd HH:mm:ss.SSS</Property>
        <Property name="CONSOLE_LOG_PATTERN">%d{${LOG_DATEFORMAT_PATTERN}} ${LOG_LEVEL_PATTERN} %pid --- [%t] %-40.40c{1.} : %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD}</Property>
    </Properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="${sys:CONSOLE_LOG_PATTERN}"/>
        </Console>
    </Appenders>
    <Loggers>
        <Logger name="com.acme" level="debug"/>
        <Root level="info">
            <AppenderRef ref="Console"/>
        </Root>
    </Loggers>
</Configuration>
0
source

All Articles