Velvet Star Monitor

Standout celebrity highlights with iconic style.

news

Init method in Spring Controller (annotation version)

Writer Sebastian Wright

I'm converting a controller to the newer annotation version. In the old version I used to specify the init method in springmvc-servlet.xml using:

<beans> <bean init-method="init"/>
</beans>

How can I specify the init method using the annotation version?

1

5 Answers

You can use

@PostConstruct
public void init() { // ...
}
3

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.

@Configuration
public 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.

@Component
public 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.

@Component
public 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 beanA
2018-11-30 18:29:30.518 DEBUG 3624 --- [ main] com.example.demo.BeanB : @PostConstruct
2018-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 beanB
2018-11-30 18:29:30.518 DEBUG 3624 --- [ main] com.example.demo.BeanA : @PostConstruct
2018-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 : @EventListener
2018-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.

@PostConstruct、implement InitializingBean、specify init-method they have call orders. So you can't use them to replace init-method. You can try this:

@Bean(initMethod = "init")
public MyBean mybean() { return new MyBean();
}
class MyBean {
public void init() { System.out.println("MyBean init");
}

}

in your class, you can declare a method named init().

Refer to:

public class InitHelloWorld implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("BeforeInitialization : " + beanName); return bean; // you can return any other object as well } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("AfterInitialization : " + beanName); return bean; // you can return any other object as well }
}

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy