Spring - Why init-method or @PostConstruct is to be used instead of InitializingBean

Published On: 2019/11/04

Why spring provides initMethod attribute in the @Bean annotation though an interface InitializingBean is part of the spring framework.

Spring framework provides many Lifecycle Callbacks to support the software development much easier. The InitializingBean callback method, afterPropertiesSet ,will be called after the container has set all necessary properties on the bean. Spring team suggest not to use the InitializingBean bean class as it unnecessarily couples the code to Spring. They suggest to use the @PostConstruct JSR-250 annotation or a POJO initialization method (@Bean attribute initMethod).

I have used first 3 beans in the below configuration to explain the 3 ways of invoking post bean initialization callback and the last bean initOrderofExecutionBean to explain the order of execution.

@Configuration
public class BeanConfig {

    @Bean
    public Jsr250SampleBean jsr250SampleBean(){
        return new Jsr250SampleBean();
    }

    @Bean(initMethod = "init")
    public PojoInitSampleBean pojoInitSampleBean(){
        return new PojoInitSampleBean();
    }

    @Bean
    public SpringwayInitializingBean springwayInitializingBean(){
        return new SpringwayInitializingBean();
    }

    @Bean(initMethod = "init")
    public InitOrderofExecutionBean initOrderofExecutionBean(){return new InitOrderofExecutionBean();}
}

@PostConstruct

This annotation marks a method that must be executed after dependency injection is performed on the class.

public class Jsr250SampleBean {

    private final static Logger LOG = LoggerFactory.getLogger(Jsr250SampleBean.class);

    public Jsr250SampleBean(){
        LOG.info("Inside Constructor");
    }

    @PostConstruct
    public void postConstruct(){
        LOG.info("Inside @PostConstruct method");
    }
}

initMethod

public class PojoInitSampleBean {

    private final static Logger LOG = LoggerFactory.getLogger(PojoInitSampleBean.class);

    public PojoInitSampleBean(){
        LOG.info("Inside Constructor");
    }

    public void init(){
        LOG.info("Inside bean init method");
    }
}

InitializingBean

public class SpringwayInitializingBean implements InitializingBean {

    private final static Logger LOG = LoggerFactory.getLogger(SpringwayInitializingBean.class);

    @Override
    public void afterPropertiesSet() throws Exception {
        LOG.info("Inside afterPropertiesSet method");
    }

}

Order of execution

public class InitOrderofExecutionBean implements InitializingBean {

    private final static Logger LOG = LoggerFactory.getLogger(InitOrderofExecutionBean.class);

    public InitOrderofExecutionBean(){
        LOG.info("Inside Constructor");
    }

    @PostConstruct
    public void postConstruct(){
        LOG.info("Inside @PostConstruct method");
    }

    public void init(){
        LOG.info("Inside bean init method");
    }

    @Override
    public void afterPropertiesSet() throws Exception {

    }
}

As you can see in the below output, first bean is created using consturctor and then the PostConstruct method is invoked and after that the init method of the bean is invoked.

2019-11-04 07:30:51.773  INFO 4364 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2148 ms
2019-11-04 07:30:51.841  INFO 4364 --- [           main] c.a.s.jsr250.InitOrderofExecutionBean    : Inside Constructor
2019-11-04 07:30:51.842  INFO 4364 --- [           main] c.a.s.jsr250.InitOrderofExecutionBean    : Inside @PostConstruct method
2019-11-04 07:30:51.842  INFO 4364 --- [           main] c.a.s.jsr250.InitOrderofExecutionBean    : Inside afterPropertiesSet method
2019-11-04 07:30:51.843  INFO 4364 --- [           main] c.a.s.jsr250.InitOrderofExecutionBean    : Inside bean init method
2019-11-04 07:30:52.035  INFO 4364 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'

Conclusion

If possible it is always better to avoid coupling to the underlying frameworks. To know the recommendation of Spring team on bean initialization please read the section Initialization Callbacks

comments powered by Disqus