@PostConstruct用法
一、介绍:
PostConstruct 是 Java EE(现 Jakarta EE)的注解,Spring 也支持。它用于标记一个方法,在 Bean 初始化完成后、依赖注入完成之后 立即执行。
执行时机:Bean 实例化 → 依赖注入 → @PostConstruct → Bean 准备就绪
二、基本用法:
package com.csii.test.spring;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
@Slf4j
public class TestPostConstructService {
@PostConstruct
public void init() {
log.info("Bean 初始化完成,执行初始化逻辑");
loadConfigurations();
initializeResources();
}
private void loadConfigurations() {
log.info("加载配置...");
}
private void initializeResources() {
log.info("初始化资源...");
}
}
启动项目,查看打印日志:
2026-01-20 14:43:21.266 INFO 23888 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2026-01-20 14:43:21.279 INFO 23888 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2026-01-20 14:43:21.279 INFO 23888 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.30]
2026-01-20 14:43:21.399 INFO 23888 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2026-01-20 14:43:21.399 INFO 23888 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 1197 ms
2026-01-20 14:43:21.499 INFO 23888 --- [ main] c.c.t.spring.TestPostConstructService : Bean 初始化完成,执行初始化逻辑
2026-01-20 14:43:21.499 INFO 23888 --- [ main] c.c.t.spring.TestPostConstructService : 加载配置...
2026-01-20 14:43:21.499 INFO 23888 --- [ main] c.c.t.spring.TestPostConstructService : 初始化资源...
2026-01-20 14:43:21.657 INFO 23888 --- [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor'
2026-01-20 14:43:21.896 INFO 23888 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
三、常见使用场景:
场景1:数据初始化
@Component
public class CacheManager {
private Map<String, Object> cache;
@PostConstruct
public void initCache() {
cache = new ConcurrentHashMap<>();
// 从数据库加载初始数据到缓存
loadInitialDataToCache();
System.out.println("缓存初始化完成");
}
}
场景2:配置验证
@Configuration
public class AppConfig {
@Value("${app.max.connections}")
private int maxConnections;
@PostConstruct
public void validateConfig() {
if (maxConnections <= 0) {
throw new IllegalArgumentException("最大连接数必须大于0");
}
System.out.println("配置验证通过");
}
}
场景3:注册监听器或处理器:
@Component
public class EventProcessor {
@Autowired
private ApplicationEventPublisher eventPublisher;
private List<EventListener> listeners = new ArrayList<>();
@PostConstruct
public void registerListeners() {
listeners.add(new EmailEventListener());
listeners.add(new SmsEventListener());
listeners.add(new LogEventListener());
// 注册到事件发布器
listeners.forEach(listener ->
eventPublisher.addApplicationListener(listener)
);
}
}
四、与InitializingBean接口比较
// 使用 @PostConstruct(推荐)
@Component
public class MyService1 {
@PostConstruct
public void init() {
// 初始化代码
}
}
// 使用 InitializingBean 接口
@Component
public class MyService2 implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
// 初始化代码
}
}
// 两者可以共存,执行顺序:@PostConstruct → afterPropertiesSet()
五、实际项目中的最佳实践
实践1:初始化配置类
@Configuration
@PropertySource("classpath:application.properties")
public class DatabaseConfig {
@Value("${spring.datasource.url}")
private String dbUrl;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
private DataSource dataSource;
@PostConstruct
public void initDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(dbUrl);
config.setUsername(username);
config.setPassword(password);
config.setMaximumPoolSize(20);
config.setMinimumIdle(5);
this.dataSource = new HikariDataSource(config);
System.out.println("数据源初始化完成");
}
@Bean
public DataSource dataSource() {
return dataSource;
}
}
六、替代方案:ApplicationRunner或CommandLineRunner:
对于需要在所有Bean初始化完成后执行的启动逻辑:
@Component
@Order(1) // 可以指定执行顺序
public class AppStartupRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
// 在所有 Bean 初始化完成后执行
System.out.println("应用启动完成,执行启动任务");
}
}
// 或者使用 CommandLineRunner
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
// 处理命令行参数
}
}
--
浙公网安备 33010602011771号