惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - 有点懒惰的大青年

用一个实际业务场景演示ON和WHERE的正确使用方式 idea中查看源码 异或运算 使用Hutool对时间的花式操作 合并K个升序列表 比较器 枚举类的设计模式 spring boot中使用RedissonClient实现分布式锁 idea同时启动application,启用不同端口 ApplicationContext 事件发布与监听机制详解 java自带命令jps介绍 关于maven中标签的说明 mysql的跨库查询 linux命令ll显示结果的含义 Files类的使用 java环境变量设置 java值传递和引用传递 kafka的集群与可靠性 kafka的消费全流程 关于kafka 达梦数据库执行计划介绍 关于MQ 用位运算实现加减乘除(3)
@PostConstruct用法
有点懒惰的大青年 · 2026-01-20 · via 博客园 - 有点懒惰的大青年

一、介绍:    

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 {
        // 处理命令行参数
    }
}

总结

  • @PostConstruct 在单个 Bean 初始化完成后立即执行

  • 适合执行该 Bean 自身的初始化逻辑

  • 不要在其中执行耗时操作

  • 对于需要在所有 Bean 都准备好后执行的逻辑,使用 ApplicationRunner 或 CommandLineRunner

--