Init method in Spring Controller (annotation version) Init method in Spring Controller (annotation version) java java

Init method in Spring Controller (annotation version)


You can use

@PostConstructpublic void init() {   // ...}


Alternatively you can have your class implement the InitializingBean interface to provide a callback function (afterPropertiesSet()) which the ApplicationContext will invoke when the bean is constructed.


There are several ways to intercept the initialization process in Spring. If you have to initialize all beans and autowire/inject them there are at least two ways that I know of that will ensure this. I have only testet the second one but I belive both work the same.

If you are using @Bean you can reference by initMethod, like this.

@Configurationpublic class BeanConfiguration {  @Bean(initMethod="init")  public BeanA beanA() {    return new BeanA();  }}public class BeanA {  // method to be initialized after context is ready  public void init() {  }} 

If you are using @Component you can annotate with @EventListener like this.

@Componentpublic class BeanB {  @EventListener  public void onApplicationEvent(ContextRefreshedEvent event) {  }}

In my case I have a legacy system where I am now taking use of IoC/DI where Spring Boot is the choosen framework. The old system brings many circular dependencies to the table and I therefore must use setter-dependency a lot. That gave me some headaches since I could not trust @PostConstruct since autowiring/injection by setter was not yet done. The order is constructor, @PostConstruct then autowired setters. I solved it with @EventListener annotation which wil run last and at the "same" time for all beans. The example shows implementation of InitializingBean aswell.

I have two classes (@Component) with dependency to each other. The classes looks the same for the purpose of this example displaying only one of them.

@Componentpublic class BeanA implements InitializingBean {  private BeanB beanB;  public BeanA() {    log.debug("Created...");  }  @PostConstruct  private void postConstruct() {    log.debug("@PostConstruct");  }  @Autowired  public void setBeanB(BeanB beanB) {    log.debug("@Autowired beanB");    this.beanB = beanB;  }  @Override  public void afterPropertiesSet() throws Exception {    log.debug("afterPropertiesSet()");  }  @EventListener  public void onApplicationEvent(ContextRefreshedEvent event) {    log.debug("@EventListener");  } }

This is the log output showing the order of the calls when the container starts.

2018-11-30 18:29:30.504 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : Created...2018-11-30 18:29:30.509 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : Created...2018-11-30 18:29:30.517 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @Autowired beanA2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @PostConstruct2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : afterPropertiesSet()2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @Autowired beanB2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @PostConstruct2018-11-30 18:29:30.518 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : afterPropertiesSet()2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanA                   : @EventListener2018-11-30 18:29:30.607 DEBUG 3624 --- [           main] com.example.demo.BeanB                   : @EventListener

As you can see @EventListener is run last after everything is ready and configured.