Mastering Spring Bean Initialization: @PostConstruct, InitializingBean, and init‑method Explained
This article explains the three Spring bean initialization callbacks—@PostConstruct, InitializingBean, and init‑method—their fixed execution order, underlying processing mechanisms, code examples, and guidance on choosing the most suitable approach for different development scenarios.
Interview Answer: Bean Initialization Callback Mechanism in Spring
The three initialization callbacks provided by Spring— @PostConstruct annotation, InitializingBean interface, and the custom init‑method configuration—are executed in a fixed order after dependency injection and before the bean is ready for use.
First, methods annotated with @PostConstruct are invoked, then the afterPropertiesSet() method of InitializingBean, and finally the user‑defined init‑method.
1. @PostConstruct Annotation
Originates from the JSR‑250 specification and is a standard Java EE annotation.
Processed by Spring's CommonAnnotationBeanPostProcessor.
Invoked via reflection on the annotated method.
package com.qy.demo;
import javax.annotation.PostConstruct;
public class PostConstructBean {
public PostConstructBean() {
System.out.println("Constructor executed - Bean instantiated");
}
@PostConstruct
public void initialize() {
System.out.println("@PostConstruct method executed - resource initialization");
}
}2. InitializingBean Interface
Spring‑provided interface.
Requires implementation of the afterPropertiesSet() method.
Called directly without reflection, offering slightly better performance.
package com.qy.demo;
import org.springframework.beans.factory.InitializingBean;
public class InitializingBeanDemo implements InitializingBean {
public InitializingBeanDemo() {
System.out.println("Constructor executed - Bean instantiated");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet() executed - resource initialization");
}
}3. init‑method Configuration
Pure configuration, specified in XML or @Bean annotation.
Invoked via reflection.
Fully decoupled; no need to implement Spring‑specific interfaces or annotations.
package com.qy.demo;
public class InitMethodBean {
public InitMethodBean() {
System.out.println("Constructor executed - Bean instantiated");
}
public void init() {
System.out.println("Custom init‑method executed - resource initialization");
}
}Configuration examples:
// Java configuration
@Bean(initMethod = "init")
public InitMethodBean initMethodBean() {
return new InitMethodBean();
} <!-- XML configuration -->
<bean id="initMethodBean" class="com.qy.demo.InitMethodBean" init-method="init" />Execution Order and Internal Principle
The execution order is fixed: @PostConstruct annotated method. InitializingBean.afterPropertiesSet() method.
Custom init‑method method.
Method Call Stack
Spring’s AbstractAutowireCapableBeanFactory.initializeBean() orchestrates the three callbacks.
AbstractApplicationContext.refresh()
-> finishBeanFactoryInitialization(beanFactory)
-> DefaultListableBeanFactory.preInstantiateSingletons()
-> getBean() -> createBean()
-> doCreateBean()
-> initializeBean(beanName, exposedObject, mbd)
-> applyBeanPostProcessorsBeforeInitialization() // @PostConstruct
-> invokeInitMethods() // InitializingBean & init‑method
-> applyBeanPostProcessorsAfterInitialization()@PostConstruct Processing
CommonAnnotationBeanPostProcessor(subclass of InitDestroyAnnotationBeanPostProcessor) scans for @PostConstruct methods after bean instantiation and invokes them via reflection.
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
} catch (Throwable ex) {
// handle exception
}
return bean;
}InitializingBean Processing
If the bean implements InitializingBean, Spring directly calls afterPropertiesSet() without reflection.
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// then init‑method handling
}init‑method Handling
Spring retrieves the method name from the bean definition and invokes it via reflection.
protected void invokeCustomInitMethod(String beanName, Object bean, RootBeanDefinition mbd) throws Throwable {
Method initMethod = ClassUtils.getMethod(bean.getClass(), mbd.getInitMethodName());
ReflectionUtils.makeAccessible(initMethod);
initMethod.invoke(bean);
}Choosing the Right Initialization Approach
@PostConstruct
Pros: Standard Java annotation, reusable outside Spring.
Cons: Requires source code and annotation support.
Best for: Annotation‑driven development, e.g., JPA entities.
InitializingBean
Pros: Tight Spring integration, direct method call.
Cons: Couples code to Spring.
Best for: Internal Spring components needing lifecycle integration.
init‑method
Pros: Fully decoupled, works with third‑party classes.
Cons: String‑based configuration prone to typos.
Best for: Config‑driven setups, third‑party library initialization.
Typical Application Scenarios
Resource Initialization : Starting connection pools, pre‑warming caches.
Parameter Validation : Ensuring required dependencies are injected.
Background Task Startup : Launching scheduled jobs or listeners.
@PostConstruct
public void initializeCache() {
System.out.println("Initializing cache");
// preload cache data
} @Override
public void afterPropertiesSet() {
if (dataSource == null) {
throw new IllegalStateException("dataSource must be set");
}
} public void init() {
System.out.println("Starting background scheduled tasks");
scheduler.startTasks();
}Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Xuanwu Backend Tech Stack
Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
