@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
@PostConstruct
public void postConstruct() {
// Called after dependency injection
}
@Override
public void afterPropertiesSet() {
// Called after postConstruct
}
@PreDestroy
public void preDestroy() {
// Called before bean destruction
}
@Override
public void destroy() {
// Called after preDestroy
}
}
// Bean definition callbacks
@Bean(initMethod = "init", destroyMethod = "cleanup")
public DataSource dataSource() {
return new HikariDataSource();
}Lifecycle Order: Constructor → @PostConstruct → InitializingBean.afterPropertiesSet() → init-method → Bean Ready → @PreDestroy → DisposableBean.destroy() → destroy-method
@Component
public class TaskExecutor implements Lifecycle {
private volatile boolean running = false;
@Override
public void start() {
if (!running) {
running = true;
// Start background tasks
}
}
@Override
public void stop() {
if (running) {
running = false;
// Stop background tasks
}
}
@Override
public boolean isRunning() {
return running;
}
}
// SmartLifecycle for phase-based startup/shutdown
@Component
public class DatabaseConnectionPool implements SmartLifecycle {
private volatile boolean running = false;
@Override
public void start() {
running = true;
// Initialize connection pool
}
@Override
public void stop() {
running = false;
// Close connections
}
@Override
public boolean isRunning() {
return running;
}
@Override
public int getPhase() {
return Integer.MAX_VALUE - 1000; // Start early, stop late
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable callback) {
stop();
callback.run(); // Signal completion
}
}// Standard events
ContextRefreshedEvent // Context initialized or refreshed
ContextStartedEvent // Context started via start()
ContextStoppedEvent // Context stopped via stop()
ContextClosedEvent // Context closed via close()
RequestHandledEvent // HTTP request handled (web apps)
// Listener implementation
@Component
public class ContextEventListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext context = event.getApplicationContext();
// Perform post-initialization tasks
}
}
// Annotation-based listener
@Component
public class EventHandlers {
@EventListener
public void handleContextRefresh(ContextRefreshedEvent event) {
// Handle refresh
}
@EventListener(condition = "#event.applicationContext.environment.acceptsProfiles('prod')")
public void handleStartupInProd(ContextStartedEvent event) {
// Conditional handling
}
@EventListener
@Order(1) // Execution order
public void handleClosing(ContextClosedEvent event) {
// Cleanup before close
}
}@Component
public class ContextAwareBean implements ApplicationContextAware,
BeanNameAware,
BeanFactoryAware,
EnvironmentAware,
ResourceLoaderAware {
private ApplicationContext context;
private String beanName;
private BeanFactory beanFactory;
private Environment environment;
private ResourceLoader resourceLoader;
@Override
public void setApplicationContext(ApplicationContext context) {
this.context = context;
}
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void setBeanFactory(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
}@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// Called before init callbacks (@PostConstruct, afterPropertiesSet)
if (bean instanceof CustomInterface) {
// Modify or wrap bean
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// Called after init callbacks
if (bean instanceof NeedsProxy) {
return createProxy(bean);
}
return bean;
}
}@Component
public class ConnectionFactoryBean implements FactoryBean<Connection> {
@Value("${db.url}")
private String url;
@Override
public Connection getObject() throws Exception {
return DriverManager.getConnection(url);
}
@Override
public Class<?> getObjectType() {
return Connection.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
// Usage:
// @Autowired Connection connection; // Gets actual Connection
// @Autowired FactoryBean factory; // Gets ConnectionFactoryBean (use &beanName)