Java spring 注解 @PostConstruct 实战讲解

前言

在最近的学习中,发现了一个非常实用的注解 ------ @PostConstruct。通过学习了解,逐步发现它能帮助我更轻松的解决不少原本很复杂的问题。

下面,结合实例介绍 @PostConstruct 注解的特性,因为@PreDestroy基本用不到,所以不浪费篇幅啦。


正文

1. 适用场景

@PostConstruct 是Java5的时候引入的注解,作用在Servlet生命周期上,实现在Bean初始化之前自定义操作。在项目中,@PostConstruct注解主要是在Servlet初始化之前加载一些缓存数据,如:数据字典,读取properties配置文件等。

通常,@PostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。

总结一下 @PostConstruct 的使用和特点:

  • 只有一个非静态方法能使用此注解;
  • 被注解的方法不得有任何参数;
  • 被注解的方法返回值必须为void;
  • 被注解方法不得抛出已检查异常;
  • 此方法只会被执行一次;

2.执行顺序

往往我们在项目启动时需要加载某个方法的时候,可以使用@Component和@PostConstruct组合将一个方法完成初始化操作,@PostConstruct 注解的方法会将在依赖注入完成之后被自动调用。

该注解在整个Bean初始化中执行的顺序:@Constructor(构造方法)-> @Autowired(依赖注入)-> @PostConstruct(注解的方法)。

3.注意事项

使用此注解时会影响服务启动时间。服务启动时会扫描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包。

4.案例分析

上面提到过, @PostConstruct 可以在Servlet初始化之前加载一些缓存数据,如:预热数据字典,读取properties配置文件,那案例就模拟这两个场景:

4.1 数据预热

使用Redis进行的数据预热,需要项目启动以后,触发第一次调用才能生成缓存,而利用 @PostConstruct 注解能让预热数据在Bean初始化阶段完成,比Redis更早。

  • @Component+@PostConstruct完成预热
java 复制代码
@Slf4j
@Configuration
public class BeanConfiguration {

    @Autowired
    private BusinessService businessService;

    // 模拟预热的数据
    private static String mysql_data;

    @PostConstruct
    public void construct(){
        log.info("〓〓〓〓〓〓〓〓〓〓 Autowired 加载完成!!");
        mysql_data = businessService.demo5();
        log.info("〓〓〓〓〓〓〓〓〓〓 mysql_data = " + mysql_data);
    }
}
  • BusinessService 演示
java 复制代码
@Slf4j
@Service
public class BusinessServiceImpl implements BusinessService {

    /**
     * 模拟从数据库查询数据的操作
     */
    public String demo5() {
        log.info("〓〓〓〓〓〓〓〓〓〓 demo5:执行!!");
        return "mysql data";
    }
}
  • 执行效果:可以看到,数据的加载是在依赖注入之后,项目启动完成之前

4.2 加载配置文件

@Value 注解修饰的常量不能是静态的,否则会 null,因为 static 的加载在 @Value 之前。如果不是 static 的,就要每次使用都要去加载一次 .properties 文件,有悖我们设置常量类的初衷。

现在,@PostConstruct注解可以帮我们完成预期,因为@PostConstruct的加载是在static之后的,不会出现null的情况,演示一下:

  • @Value获取数据,再通过@PostConstruct向static常量赋值
java 复制代码
@Slf4j
@Component
public class GlobalConstent {

    @Value("${server.port}")
    private String port;
    // 模拟静态常量
    public static String server_port;
    
    @PostConstruct
    public void construct(){
        log.info("〓〓〓〓〓〓〓〓〓〓 Before PostConstruct:" + server_port);
        server_port = port;
        log.info("〓〓〓〓〓〓〓〓〓〓 After PostConstruct:" + server_port);
    }
}
  • 使用过程很友好,直接采用"类名·"的方式访问
java 复制代码
@Slf4j
@RestController
@RequestMapping("/construct")
public class PostConstructController {

    @RequestMapping("/demo")
    public String demo() {
        log.info("〓〓〓〓〓〓〓〓〓〓 server_port:" + GlobalConstent.server_port);
        return "success";
    }
}
  • 结果展示:加载过程都在项目成功启动之前

总结

  1. @PostConstruct注解时会影响服务启动时间,服务启动时会扫描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包;
  2. @PostConstruct注解在整个Bean初始化中执行的顺序:@Constructor(构造方法)-> @Autowired(依赖注入)-> @PostConstruct(注解的方法);
  3. @PostConstruct 可以在Servlet初始化之前加载一些缓存数据,如:预热数据字典,读取properties配置文件;

相关推荐
唐青枫9 小时前
Java Flyway 实战指南:用 SQL 脚本管理数据库版本
java
huangdong_15 小时前
电商平台图片URL原图转换技术深度解析:从缩略图到高清原图的完整方案
java·后端·spring
記億揺晃着的那天16 小时前
Java 调用外部 Go 程序的实践:ProcessBuilder 在生产环境中的应用
java·golang·processbuilder
JAVA面经实录91716 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
JAVA面经实录91717 小时前
操作系统面试题
java·服务器·数据库·计算机网络·面试
一杯奶茶¥17 小时前
基于springboot的失物招领管理系统带万字文档 校园失物招领管理系统 失物认领管理系统java springboot vue
java·vue.js·spring boot·java项目
不能只会打代码17 小时前
边缘视频分析平台的架构设计与性能优化——从750ms到190ms的调优之路
java·spring boot·redis·性能优化·边缘计算·物联网竞赛
小刘|17 小时前
Spring AI Alibaba 集成和风天气 API 实战
java·服务器·前端
KANGBboy17 小时前
java知识五(继承)
java·开发语言
AI人工智能+电脑小能手17 小时前
【大白话说Java面试题 第117题】【并发篇】第17题:线程有几种状态,之间如何转换?
java·开发语言·面试