19

I have a classX in my spring application in which I want to be able to find out if all spring beans have been initialized. To do this, I am trying to listen ContextRefreshedEvent.

So far I have the following code but I am not sure if this is enough.

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

public classX implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
       //do something if all apps have initialised
    }
}
  1. Is this approach correct to find out if all beans have initialsed?
  2. What else do I need to do to be able to listen to the ContextRefreshedEvent ? DO I need to register classX somewhere in xml files ?
kk1957
  • 8,246
  • 10
  • 41
  • 63
  • 1
    Just as a supplement to the answer of Sotirios Delimanolis: if you use Spring Framework 4.2 or above you can simply annotate a method of a managed-bean with `@EventListener` to automatically register an `ApplicationListener` matching the signature of the method. Read more here: https://spring.io/blog/2015/02/11/better-application-events-in-spring-framework-4-2 – Victor Dombrovsky Nov 24 '16 at 07:49

4 Answers4

30

A ContextRefreshEvent occurs

when an ApplicationContext gets initialized or refreshed.

so you are on the right track.

What you need to do is declare a bean definition for classX.

Either with @Component and a component scan over the package it's in

@Component
public class X implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
       //do something if all apps have initialised
    }
}

or with a <bean> declaration

<bean class="some.pack.X"></bean>

Spring will detect that the bean is of type ApplicationListener and register it without any further configuration.

Later Spring version support annotation-based event listeners. The documentation states

As of Spring 4.2, you can register an event listener on any public method of a managed bean by using the @EventListener annotation.

Within the X class above, you could declare an annotated method like

@EventListener
public void onEventWithArg(ContextRefreshedEvent event) {
}

or even

@EventListener(ContextRefreshedEvent.class)
public void onEventWithout() {

}

The context will detect this method and register it as a listener for the specified event type.

The documentation goes into way more detail about the full feature set: conditional processing with SpEL expression, async listeners, etc.


Just FYI, Java has naming conventions for types, variables, etc. For classes, the convention is to have their names start with an uppercase alphabetic character.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • By the way, "As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContext actually supports such "hot" refreshes. " – Allan Ruin Mar 11 '14 at 16:51
  • I know context initialization but what is mean by `context getting refreshed` ? – Govinda Sakhare Apr 12 '16 at 11:18
  • 1
    @piechuckerr See [this](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/AbstractApplicationContext.html#refresh--). – Sotirios Delimanolis Apr 27 '16 at 18:57
15

Spring >= 4.2

You can use annotation-driven event listener as below :

@Component
public class classX  {

    @EventListener
    public void handleContextRefresh(ContextRefreshedEvent event) {

    }
}

the ApplicationListener you want to register is defined in the signature of the method.

Radouane ROUFID
  • 10,595
  • 9
  • 42
  • 80
2

(ContextRefreshedEvent event) gets called twice, one in init and secondly after init.

You can use (ApplicationReadyEvent event) and call will be made only once after init.

public class InvokeCatalogOne implements IInvokeCatalogOne {

    @EventListener
    public void fetchChargeCode(ApplicationReadyEvent event) {

    }
}
1

I will prefer ApplicationReadyEvent. I found ContextRefreshedEvent is called before my http server is started. ApplicationReadyEvent will make sure your application is ready to take request.

    @EventListener(ApplicationReadyEvent.class)
    public void startApp() {
        LOGGER.info("Application is now ready!");
    }
Manish
  • 1,452
  • 15
  • 25