首页 > Python资料 博客日记
@PostConstruct 注解分析
2024-02-26 14:00:05Python资料围观213次
一、简介
如果需要在生成对象时就完成某些初始化操作,而且这些初始化操作又依赖于依赖注入@Autowired
,那么就无法在构造函数中实现。为此,可以使用@PostConstruct
注解一个方法来完成初始化。@PostConstruct
注解的方法将会在依赖注入完成后被自动调用。类初始化调用顺序: Constructor >> @Autowired >> @PostConstruct
特点:
1、只有一个非静态方法能使用此注解;
2、被注解的方法不得有任何参数;
3、被注解的方法返回值必须为void
;
4、被注解方法不得抛出已检查异常;
5、此方法只会被执行一次;
@PostConstruct
是Java
自带的注解,在方法上添加该注解时,Spring
容器初始化的时候会执行该方法。从Java EE5
规范开始,Servlet
中存在两个注解@PostConstruct
和@PreDestroy
影响Servlet
生命周期(加载-实例化-初始化-服务-销毁),这两个注解用来修饰非静态的void
无参方法;
@PostConstruct
与@PreDestroy
区别:
【1】@PostConstruct
用于标记一个方法,在对象创建后立即执行。它通常用于执行一些初始化操作,例如初始化成员变量或建立数据库连接。
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
【2】@PreDestroy
用于标记一个方法,在对象销毁之前执行。它通常用于执行一些清理操作,例如关闭数据库连接或释放资源。
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PreDestroy {
}
@PostConstruct
和@PreDestroy
这两个注解是Java5
引入, 已经完全在Java11
中删除. 使用需要引入jar
包
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
总结来说,@PostConstruct
用于在对象创建后执行初始化操作,而@PreDestroy
用于在对象销毁前执行清理操作。这两个注解都是由依赖注入框架自动调用的,无需手动调用。
注意事项: 在使用@PostConstruct
注解时,需要注意以下几点:
【1】@PostConstruct
注解时会影响服务启动时间,服务启动时会扫描WEB-INF/classes
的所有文件和WEB-INF/lib
下的所有jar
包;
【2】@PostConstruct
注解在整个Bean初始化中执行的顺序:@Constructor
(构造方法)-> @Autowired
(依赖注入)->@PostConstruct
(注解的方法);
【3】依赖注入完成后执行,@PostConstruct
注解标记的方法将在依赖注入完成后执行。因此,在标记方法的同时,确保所需的依赖已经正确注入到对象中;
【4】方法签名和异常处理,被@PostConstruct
注解标记的方法没有特定的方法签名要求,可以是任意访问修饰符、任意返回类型和任意参数列表。然而,建议遵循一致的方法命名和参数命名规范,以提高代码的可读性。此外,被@PostConstruct
注解标记的方法应该尽量避免抛出异常。如果抛出异常,容器可能会在对象初始化过程中抛出异常并终止初始化;
【5】与构造函数的区别,@PostConstruct
注解标记的方法在对象构造函数执行完成后调用,因此可以看作是构造函数之后的进一步初始化操作。与构造函数不同,@PostConstruct
注解的方法可以访问依赖注入的成员变量,并执行更复杂的逻辑;
【6】跨平台兼容性,需要注意的是,@PostConstruct
注解是JavaEE
标准的一部分,在标准的JavaSE
中也被引入。因此,几乎所有的JavaEE
容器和一些常见的JavaSE
容器都支持@PostConstruct
注解。然而,为了确保跨平台兼容性,建议在使用之前进行适当的测试;
二、代码
@Service
public class UserAutoBookProcess{
// 使用到了依赖注入对象
@Autowired
private ChineseConfig chineseConfig;
private Map<Integer, String> map = null;
// 初始化方法
@PostConstruct
public void init(){
ImmutableMap.of(1, chineseConfig.getFirst(), 2, chineseConfig.getSecord());
}
}
三、源码分析
@PostConstruct
注解的实现原理是在Spring
容器初始化时,会扫描所有标有该注解的方法,并调用它们。如下:@PostConstruct
注解是一个标注在方法上的注解,用于标记一个方法是在bean
实例化后被调用的方法。它的定义比较简单,没有任何实现代码。
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
下面我们来看一下Spring
容器是如何扫描并调用@PostConstruct
注解的方法的:Spring
容器在初始化InitDestroyAnnotationBeanPostProcessor
这个类的内部postProcessBeforeInitialization
方法里对@PostConstruct
这个注解进行识别, 然后通过反射, 对这个方法进行了调用。而postProcessBeforeInitialization
这个方法的被调是在bean
的初始化。
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
InitDestroyAnnotationBeanPostProcessor.LifecycleMetadata metadata = this.findLifecycleMetadata(bean.getClass());
try {
metadata.invokeInitMethods(bean, beanName);
return bean;
} catch (InvocationTargetException var5) {
throw new BeanCreationException(beanName, "Invocation of init method failed", var5.getTargetException());
} catch (Throwable var6) {
throw new BeanCreationException(beanName, "Failed to invoke init method", var6);
}
}
四、实战引用
【1】Redis
工具类/初始化MQ
/数据库连接/基础数据加载等。
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class RedisUtil {
private static RedisTemplate<Object, Object> redisTemplates;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@PostConstruct
public void initialize() {
redisTemplates = this.redisTemplate;
}
/**
* 添加元素
*
* @param key
* @param value
*/
public static void set(Object key, Object value) {
if (key == null || value == null) {
return;
}
redisTemplates.opsForValue().set(key, value);
}
}
【2】我们写一个Demo
感受下@PostConstruct
在服务器加载Servlet
的时候运行指定方法,并且只运行一次。
@Component
public class PostConstructDemo {
@PostConstruct
public void testPostConstruct() {
System.out.printf("==========PostConstruct test================");
}
}
【3】@PostConstruct
自定义定时任务的用法
@Controller
public class processTimeoutController {
@Scheduled(cron = "0 * * * * ?")
@PostConstruct
public void processTimeoutMethod() {
System.out.printf("===job====" + Calendar.getInstance().getTime());
}
}
【4】配置加载和解析:在应用程序启动时,我们可能需要加载和解析一些配置文件,并将配置信息应用到相应的组件中。可以使用@PostConstruct
注解来执行这些配置加载和解析的操作。
public class AppConfig {
private Properties config;
@PostConstruct
public void init() {
// 加载和解析配置文件
config = // ...
}
}
标签:
相关文章
最新发布
- 光流法结合深度学习神经网络的原理及应用(完整代码都有Python opencv)
- Python 图像处理进阶:特征提取与图像分类
- 大数据可视化分析-基于python的电影数据分析及可视化系统_9532dr50
- 【Python】入门(运算、输出、数据类型)
- 【Python】第一弹---解锁编程新世界:深入理解计算机基础与Python入门指南
- 华为OD机试E卷 --第k个排列 --24年OD统一考试(Java & JS & Python & C & C++)
- Python已安装包在import时报错未找到的解决方法
- 【Python】自动化神器PyAutoGUI —告别手动操作,一键模拟鼠标键盘,玩转微信及各种软件自动化
- Pycharm连接SQL Sever(详细教程)
- Python编程练习题及解析(49题)
点击排行
- 版本匹配指南:Numpy版本和Python版本的对应关系
- 版本匹配指南:PyTorch版本、torchvision 版本和Python版本的对应关系
- Anaconda版本和Python版本对应关系(持续更新...)
- Python 可视化 web 神器:streamlit、Gradio、dash、nicegui;低代码 Python Web 框架:PyWebIO
- 相关性分析——Pearson相关系数+热力图(附data和Python完整代码)
- Windows上安装 Python 环境并配置环境变量 (超详细教程)
- Python与PyTorch的版本对应
- Python pyinstaller打包exe最完整教程