or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

annotation-config.mdaot.mdcaching.mdcontext-lifecycle.mdevents.mdformatting.mdi18n.mdindex.mdjmx.mdresilience.mdscheduling.mdstereotypes.mdvalidation.md
tile.json

context-lifecycle.mddocs/

Context Lifecycle

Bean Lifecycle Callbacks

@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

Lifecycle Interface

@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
    }
}

ApplicationContext Events

// 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
    }
}

ApplicationContextAware

@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;
    }
}

BeanPostProcessor

@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;
    }
}

FactoryBean

@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)