0

I have a Spring application, and Im trying to understand how long all the PostConruct takes.

but this method isn't getting called, what am I missing ?

@Component
@Aspect
@Order(1)
public class InspectorTime {


    @Around("@within(javax.annotation.PostConstruct)")
    public void beforePostConstruct(ProceedingJoinPoint joinPoint) throws Throwable {
        LOG.info("Before PostContract:{}", joinPoint.getSignature().getDeclaringType().toString());
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        joinPoint.proceed(joinPoint.getArgs());
        stopWatch.stop();
        LOG.info("After PostContract:{}", joinPoint.getSignature().getDeclaringType().toString() + ", total time" + stopWatch.toString());
    }

}

I have followed, these solutions @Before @PostConstruct Spring AOP ineterception but they also estimate the "Autowire" timing. I need to estimate the postContruct only.

I also tried this Code

@Around("@annotation(javax.annotation.PostConstruct)")
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        Object proceed = joinPoint.proceed();
        long executionTime = System.currentTimeMillis() - start;
        logger.info("{}.{} executed in {} ms", joinPoint.getSignature().getDeclaringTypeName(),
                joinPoint.getSignature().getName(), executionTime);
        return proceed;
    }

But its making my other beans to failed to instantiate:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.core.RedisTemplate]: Factory method 'redisTemplate' threw exception; nested exception is java.lang.NullPointerException
Hard Worker
  • 995
  • 11
  • 33
  • 1
    post construct is called before AOP processing has begun, so trying to intercept this in the startup cycle of the bean won't work. Use JFR events instead to investigate. – M. Deinum Jan 05 '23 at 07:05

1 Answers1

1

Don't do this yourself either use a proper profiler to get the results or start with using the [Java Flight Recorder] for which Spring has support out-of-the-box.

Spring will record startup metrics as JFR events (see the documentation) and you can record these to a file and investigate that file with Java Mission Control.

Spring will record all sorts of events for different parts of the container and bean lifecycle, see the documentation for a list.

To enable you need to register the ApplicationStartup and pass that to the ApplicationContext you are using. To record to the flight recorder you will need to create the FlightRecorderApplicationStartup.

Assuming you are using Spring Boot this is trivial to do, you pass it to the SpringApplication before running it.

@SpringBootApplication
public class MyApplication {

  public static void main(String[] args) throws Exception {
    var app = new SpringApplication(MyApplication.class);
    app.setApplicationStartup(new FlightRecorderApplicationStartup());
    app.run(args);
  }
}

Now when starting you need to enable the flight recorder and the recordings.

java -XX:+FlightRecorder -XX:StartFlightRecording=duration=30s,filename=myrecording.jfr -jar your-app.jar

This will record events for 30s and after that write a file called myrecording.jfr, which you can then open in Java Mission Control and see how long certain parts took for a bean or all beans etc. If you app takes more then 30s to startup increase the duration parameter to what you need.

If this isn't enough I would strongly suggest to use a proper profiler instead of trying to work around this with AOP as when adding AOP it will influence the time to start your application and beans (due to additional proxies being created, or you must use load- or compile time weaving).

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • What if Im using an old Spring application that is not spring boot ? – Hard Worker Jan 05 '23 at 07:22
  • You need to use at least Spring 5.3 and then it depends on how you are bootstrapping the application. If you are creating the `ApplicationContext` yourself, you can set it to the `ApplicationContext` through `setApplicationStartup`. But as you nowhere state which version or what app you are trying to investigate (Nor answer my question in your other question about the same topic). – M. Deinum Jan 05 '23 at 07:32