找回密码
 会员注册
查看: 29|回复: 0

@PostConstruct注解分析

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64454
发表于 2024-9-3 00:22:39 | 显示全部楼层 |阅读模式
一、简介如果需要在生成对象时就完成某些初始化操作,而且这些初始化操作又依赖于依赖注入@Autowired,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化。@PostConstruct注解的方法将会在依赖注入完成后被自动调用。类初始化调用顺序:Constructor>>@Autowired>>@PostConstruct特点:1、只有一个非静态方法能使用此注解;2、被注解的方法不得有任何参数;3、被注解的方法返回值必须为void;4、被注解方法不得抛出已检查异常;5、此方法只会被执行一次;@PostConstruct是Java自带的注解,在方法上添加该注解时,Spring容器初始化的时候会执行该方法。从JavaEE5规范开始,Servlet中存在两个注解@PostConstruct和@PreDestroy影响Servlet生命周期(加载-实例化-初始化-服务-销毁),这两个注解用来修饰非静态的void无参方法;@PostConstruct与@PreDestroy区别:【1】@PostConstruct用于标记一个方法,在对象创建后立即执行。它通常用于执行一些初始化操作,例如初始化成员变量或建立数据库连接。@Documented@Retention(RUNTIME)@Target(METHOD)public@interfacePostConstruct{}12345【2】@PreDestroy用于标记一个方法,在对象销毁之前执行。它通常用于执行一些清理操作,例如关闭数据库连接或释放资源。@Documented@Retention(RUNTIME)@Target(METHOD)public@interfacePreDestroy{}12345@PostConstruct和@PreDestroy这两个注解是Java5引入,已经完全在Java11中删除.使用需要引入jar包javax.annotation1.3.212345总结来说,@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注解。然而,为了确保跨平台兼容性,建议在使用之前进行适当的测试;二、代码@ServicepublicclassUserAutoBookProcess{//使用到了依赖注入对象 @Autowired privateChineseConfigchineseConfig;privateMapmap=null; //初始化方法 @PostConstruct publicvoidinit(){ImmutableMap.of(1,chineseConfig.getFirst(),2,chineseConfig.getSecord()); }}123456789101112131415三、源码分析@PostConstruct注解的实现原理是在Spring容器初始化时,会扫描所有标有该注解的方法,并调用它们。如下:@PostConstruct注解是一个标注在方法上的注解,用于标记一个方法是在bean实例化后被调用的方法。它的定义比较简单,没有任何实现代码。@Documented@Retention(RUNTIME)@Target(METHOD)public@interfacePostConstruct{}12345下面我们来看一下Spring容器是如何扫描并调用@PostConstruct注解的方法的:Spring容器在初始化InitDestroyAnnotationBeanPostProcessor这个类的内部postProcessBeforeInitialization方法里对@PostConstruct这个注解进行识别,然后通过反射,对这个方法进行了调用。而postProcessBeforeInitialization这个方法的被调是在bean的初始化。publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{InitDestroyAnnotationBeanPostProcessor.LifecycleMetadatametadata=this.findLifecycleMetadata(bean.getClass());try{metadata.invokeInitMethods(bean,beanName);returnbean;}catch(InvocationTargetExceptionvar5){thrownewBeanCreationException(beanName,"Invocationofinitmethodfailed",var5.getTargetException());}catch(Throwablevar6){thrownewBeanCreationException(beanName,"Failedtoinvokeinitmethod",var6);}}123456789101112四、实战引用【1】Redis工具类/初始化MQ/数据库连接/基础数据加载等。importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importjavax.annotation.PostConstruct;@ComponentpublicclassRedisUtil{privatestaticRedisTemplateredisTemplates;@AutowiredprivateRedisTemplateredisTemplate;@PostConstructpublicvoidinitialize(){redisTemplates=this.redisTemplate;}/***添加元素**@paramkey*@paramvalue*/publicstaticvoidset(Objectkey,Objectvalue){if(key==null||value==null){return;}redisTemplates.opsForValue().set(key,value);}}123456789101112131415161718192021222324252627282930313233【2】我们写一个Demo感受下@PostConstruct在服务器加载Servlet的时候运行指定方法,并且只运行一次。@ComponentpublicclassPostConstructDemo{@PostConstructpublicvoidtestPostConstruct(){System.out.printf("==========PostConstructtest================");}}1234567【3】@PostConstruct自定义定时任务的用法@ControllerpublicclassprocessTimeoutController{@Scheduled(cron="0****?")@PostConstructpublicvoidprocessTimeoutMethod(){System.out.printf("===job===="+Calendar.getInstance().getTime());}}12345678【4】配置加载和解析:在应用程序启动时,我们可能需要加载和解析一些配置文件,并将配置信息应用到相应的组件中。可以使用@PostConstruct注解来执行这些配置加载和解析的操作。publicclassAppConfig{privatePropertiesconfig;@PostConstructpublicvoidinit(){//加载和解析配置文件config=//...}}123456789
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:02 , Processed in 0.497474 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表