@PostConstruct注解详解

简介

javaEE5引入了@PostConstruct和@PreDestroy两个作用于Servlet生命周期的注解,实现Bean初始化之前和销毁之前的自定义操作

使用场景

在项目中主要是在Servlet初始化之前加载一些缓存数据等

API使用说明

PostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。此方法必须在将类放入服务之前调用。支持依赖关系注入的所有类都必须支持此注释。即使类没有请求注入任何资源,用 PostConstruct 注释的方法也必须被调用。只有一个方法可以用此注释进行注释。应用 PostConstruct 注释的方法必须遵守以下所有标准:该方法不得有任何参数,除非是在 EJB 拦截器 (interceptor) 的情况下,根据 EJB 规范的定义,在这种情况下它将带有一个 InvocationContext 对象 ;该方法的返回类型必须为 void;该方法不得抛出已检查异常;应用 PostConstruct 的方法可以是 public、protected、package private 或 private;除了应用程序客户端之外,该方法不能是 static;该方法可以是 final;如果该方法抛出未检查异常,那么不得将类放入服务中,除非是能够处理异常并可从中恢复的 EJB。

特点:

1、只有一个非静态方法能使用此注解

2、被注解的方法不得有任何参数

3、被注解的方法返回值必须为void

4、被注解方法不得抛出已检查异常

5、此方法只会被执行一次

servlet执行流程

img

注意事项

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

@PostConstruct注解的用法

@PostConstruct是java5的时候引入的注解,指的是在项目启动的时候执行这个方法,也可以理解为在spring容器启动的时候执行,可作为一些数据的常规化加载,比如数据字典之类的。

被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行

也就是加载顺序

服务器加载Servlet -> servlet 构造函数的加载 -> postConstruct ->init(init是在service 中的初始化方法. 创建service 时发生的事件.) ->Service->destory->predestory->服务器卸载serlvet

那么问题:spring中Constructor、@Autowired、@PostConstruct的顺序
Constructor >> @Autowired >> @PostConstruct

依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入。所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发生在A的构造方法执行完之后的。

@PostConstruct应用场景:
如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。

@PostConstructpublic void start() {try {int connect = producer.connect();if (connect == 0) {log.info("producer start success! groupName:{},namesrvAddr:{}", rocketMqProperties.getProducer().getGroupName(), rocketMqProperties.getNamesrvAddr());}} catch (MQException e) {e.printStackTrace();}
}@PreDestroypublic void stop()  {try {if (producer != null) {producer.close();log.info("producer closed");}}catch (MQException a){a.printStackTrace();}
}

在最近的工作中,get到一个很实用的注解,分享给诸位。

痛点

做过微信或支付宝支付的童鞋,可能遇到过这种问题,就是填写支付结果回调,就是在支付成功之后,支付宝要根据我们给的地址给我们进行通知,通知我们用户是否支付成功,如果成功我们就要去处理下面相应的业务逻辑,如果在测试服务,那么这个回调地址我们就需要填写测试服务的,如果发布到线上那么我们就需要改成线上的地址。

针对上面的场景,我们一般都会通过如下的方式,进行一个动态配置,不需要每次去改,防止出现问题。

public class PayTest {@Value("${spring.profiles.active}")private String environment;public Object notify(HttpServletRequest request) {if ("prod".equals(environment)) {// 正式环境} else if ("test".equals(environment)) {// 测试环境}return "SUCCESS";}
}

上面的代码看起来没有一点问题,但是身为搬砖的我们咋可能这样搬,姿势不对呀!

问题:

扩展性太差,如果这个参数我们还需要在别的地方用到,那么我们是不是还要使用@Value的注解获取一遍,假如有天我们的leader突然说吗,test这个单词看着太low了,换个高端一点的,换成dev,那么我们是不是要把项目中所有的test都要改过来,如果少还好,要是很多,那我们怕不是凉了。

所以我们能不能将这些配置参数搞成一个全局的静态变量,这样的话我们直接饮用就好了,哪怕到时候真的要改,那我也只需要改动一处就好了。

注意大坑

有的朋友可能就比较自信了,那我直接加个static修饰下不就好了,如果你真是打算这样做,那你就准备卷好铺盖走人吧。直接加static获取到的值其实是一个null,至于原因,大家复习下类以及静态变量变量的加载顺序。

@PostConstruct注解

那么既然说出了问题,肯定就有解决方法,不然你以为我跟你玩呢。

首先这个注解是由Java提供的,它用来修饰一个非静态的void方法。它会在服务器加载Servlet的时候运行,并且只运行一次

改造:

@Component
public class SystemConstant {public static String surroundings;@Value("${spring.profiles.active}")public String environment;@PostConstructpublic void initialize() {System.out.println("初始化环境...");surroundings = this.environment;}
}

结果:

我们可以看到在项目启动的时候进行了初始化

img

到这里我们已经可以拿到当前运行的环境是测试还是正式,这样就可以做到动态配置

img

最后想说

其实这个注解远不止这点用处,像我之前写的Redis工具类,我使用的是RedisTemplate操作Redis,导致写出来的方法没办法用static修饰,每次使用Redis工具类只能先注入到容器然后再调用,使用了这个注解就可以完美的解决这种尴尬的问题。代码如下。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;/*** @ClassName RedisUtil* @Description TODO* @Version 1.0*/
@Component
public class RedisUtil {private static RedisTemplate<Object, Object> redisTemplates;@Autowiredprivate RedisTemplate<Object, Object> redisTemplate;@PostConstructpublic 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);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用户密码到底要怎样存储?

作为互联网公司的信息安全从业人员经常要处理撞库扫号事件&#xff0c;产生撞库扫号的根本原因是一些企业发生了信息泄露事件&#xff0c;且这些泄露数据未加密或者加密方式比较弱&#xff0c;导致黑客可以还原出原始的用户密码。 目前已经曝光的信息泄露事件至少上百起&#…

dateframe取某列数据_Python获取时序数据并进行可视化分析

更多精彩&#xff0c;请点击上方蓝字关注我们&#xff01;1. 准备工作tushare是一个第三方财经数据接口包&#xff0c;需要安装包并完成注册。安装tushare包pip install tushare 为防恶意调用接口数据&#xff0c;官方()需要新用户完成注册、提高积分(例如达到200)、取得访问权…

Shiro 登录认证源码详解

Apache Shiro 是一个强大且灵活的 Java 开源安全框架&#xff0c;拥有登录认证、授权管理、企业级会话管理和加密等功能&#xff0c;相比 Spring Security 来说要更加的简单。 本文主要介绍 Shiro 的登录认证&#xff08;Authentication&#xff09;功能&#xff0c;主要从 Sh…

中3d库后接负载_Nature子刊:近红外光交联水凝胶用于活体生物3D打印

由于打印精度高、速度快&#xff0c;光固化3D打印成为组织再生等医学研究的有利工具&#xff0c;然而由于现在光固化3D打印普遍采用波长较短的光源&#xff0c;对组织损害较大且穿透力不高&#xff0c;这大大限制生物体内3D打印的发展。最近&#xff0c;来自意大利帕多瓦大学的…

怎么看调用的接口_Hadoop RPC调用实例分析

以ClientProtocol接口中的rename RPC调用进行一次实例分析。rename方法在ClientProtocol接口中定义&#xff0c;它的两个参数是String类型的&#xff0c;不能直接通过网络传输。我们看谁实现了ClientProtocol接口并重写rename方法。看到是ClientNamenodeProtocolTranslatorPB这…

父子结构查询_Java面试准备(5)之数据结构与算法——红黑树

欢迎点赞评论关注~~~~~~~如上图&#xff0c;二叉查找树极端情况下可能会变成一个单链表&#xff0c;这种查询时间复杂度就变成O(n)了&#xff0c;红黑树在二叉查找树的基础上进行了自平衡。1.原理分析如上图&#xff0c;红黑树具有以下特征&#xff1a;1. 每个节点要么是黑色&a…

中海达数据怎么转rinex_cors账号网最新实战教程,中海达 F61 Plus RTK连接千寻cors账号的方法...

RTK在工程测量工作中越来越流行&#xff0c;在这股潮流中&#xff0c;中海达品牌的F61 Plus因为融合了中海达多年的成熟建站技术HD-CORS&#xff0c;在工程测量工作中也受到了很大欢迎。它可以配套各种cors账号使用&#xff0c;使用过程中只需一台RTK移动站即可进行数据采集、施…

Shiro之UsernamePasswordTokenRememberMeAuthenticationTokenAuthenticationToken

继承关系 先看一下三者的继承关系&#xff0c;会有一个比较清楚的认识 AuthenticationToken AuthenticationToken 用于收集用户提交的身份&#xff08;如用户名&#xff09;及凭据&#xff08;如密码&#xff09;。Shiro会调用CredentialsMatcher对象的doCredentialsMatch方法对…

华为手机滑动速度设置_华为手机打字速度慢?开启这个设置,一分钟就能打200字...

很多朋友都说自己的打字速度非常慢&#xff01;每次使用手机聊天、记录工作事项大半天还没打一段字来。其实使用华为手机就能非常快速的码字&#xff0c;不管聊天还是工作&#xff0c;使用这个方法&#xff0c;一分钟就能打200字。1.聊天快速打字手机键盘因为体积的原因&#x…

SpringBoot 使用AOP功能

RPC&#xff0c;AOP都会用到代理&#xff0c;代理的技术有jdk的Proxy代理(必须实现接口)&#xff0c;cglib(可以不实现接口&#xff0c;直接实现类)&#xff0c;Javassist(jboss )而Spring boot本身也在方方面面使用了代理技术,在Spring中有两种动态代理方式&#xff0c;分别为…

cognos报表导出excel_有了这个报表工具,一键生成自定义的各种报表,还可以导出Excel...

EasyReport是一个简单易用的Web报表工具,它的主要功能是把SQL语句查询出的数据转换成报表页面&#xff0c; 同时支持表格的跨行(RowSpan)与跨列(ColSpan)配置。 同时它还支持报表Excel导出、图表显示及固定表头与左边列的功能。功能介绍本工具从数据库(MySQL,Oracle,SQLServer,…

java自定义注解实现日志功能

一、spring aop的通知类型 1、前置通知&#xff08;Before&#xff09;&#xff1a;在连接点前执行&#xff0c;不会影响连接点的执行&#xff0c;除非抛异常&#xff1b; 2、后置通知&#xff08;AfterReturning&#xff09;&#xff1a;在连接点正常执行完成后执行&#xff0…

java自定义注解annotation记录操作日志

说到注解我们平常用的可以说非常多啦&#xff0c;说几个常用的的注解 RestController Service Autowired 这些都是我们平常使用spring框架最常见的注解了&#xff0c;我们只知道它们非常好用&#xff0c;使用RestController 就能构建一个restful的控制器,Service 这个是我们常用…

数组concat_js 标准二维数组变一维数组的方法

问题&#xff1a;[[1, 1], [2, 3], [4, 5]] -> [1, 1, 2, 3, 4, 5]&#xff1f;方法一利用es5的arr.reduce(callback[, initialValue])实现var arr1 [[0, 1], [2, 3], [4, 5]]; var arr2 arr1.reduce(function (a, b) { return a.concat(b)} ); // arr2 [0, 1, 2, 3, 4, 5…

java 自定义注解+AOP实现日志记录

ssm版本&#xff1a; 1、首先自定义一个注解&#xff0c;该注解有两个属性&#xff0c;一个是模块名&#xff0c;一个是操作的内容。该注解是用来修饰Service层中的方法的。 2、创建一个切面类&#xff0c;该切面使用Aspect和Component注解修饰&#xff0c;该页面需要注入一个…

是人是谁_谁是白鹤滩最可爱的人

白鹤滩水电站是全球在建第一大水电站&#xff0c;主要特性指标均位居世界水电工程前列&#xff0c;2021年7月&#xff0c;首批机组投产发电将是白鹤滩工程为建党一百周年献礼的重大壮举。建设中的白鹤滩水电站工程建设不停步&#xff0c;白鹤滩水电站未来的运行管理者——白鹤滩…

potplayer 多个进程_进程组、会话、控制终端概念,如何创建守护进程?

守护进程概念&#xff1a;守护进程&#xff0c;也就是通常所说的Daemon进程&#xff0c;是Linux中的后台服务进程。周期性的执行某种任务或等待处理某些发生的事件。Linux系统有很多守护进程&#xff0c;大多数服务都是用守护进程实现的。比如&#xff1a;像我们的tftp&#xf…

acs880 用户手册_华中数控、广州数控系统用户手册

数控加工仿真系统 广州数控系统用户手册上海宇龙软件工程有限公司2004 年 5 月华中数控、广州数控系统用户手册 目录I目录第一章 基本操作 ............................................................................................ 1 1.1 项目文件 ...................…

亚马逊出的平板电脑_美国最畅销的安卓平板电脑,还只有2GB内存

在美国除了iPad&#xff0c;谁家的平板电脑卖得最好&#xff1f;不是华为小米&#xff0c;也不是微软或谷歌&#xff0c;而是Amazon亚马逊。主打入门级定位的亚马逊Fire系列平板电脑&#xff0c;在北美的平板市场上&#xff0c;有着举足轻重的地位。今天&#xff0c;亚马逊正式…

对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...

​前言在本文开始之前&#xff0c;作者一直有个疑惑&#xff0c;就是面试题是只写写问题和答案就草草了事&#xff0c;还是应该深入分析一下其背后发生的一些原理。和朋友探讨以后作者还是决定采用后者的方式&#xff0c;因为我认为不仅要做到知其一&#xff0c;更要知其二&…