日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

@PostConstruct注解详解

發(fā)布時(shí)間:2025/3/12 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @PostConstruct注解详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

簡(jiǎn)介

javaEE5引入了@PostConstruct和@PreDestroy兩個(gè)作用于Servlet生命周期的注解,實(shí)現(xiàn)Bean初始化之前和銷毀之前的自定義操作

使用場(chǎng)景

在項(xiàng)目中主要是在Servlet初始化之前加載一些緩存數(shù)據(jù)等

API使用說(shuō)明

PostConstruct 注釋用于在依賴關(guān)系注入完成之后需要執(zhí)行的方法上,以執(zhí)行任何初始化。此方法必須在將類放入服務(wù)之前調(diào)用。支持依賴關(guān)系注入的所有類都必須支持此注釋。即使類沒(méi)有請(qǐng)求注入任何資源,用 PostConstruct 注釋的方法也必須被調(diào)用。只有一個(gè)方法可以用此注釋進(jìn)行注釋。應(yīng)用 PostConstruct 注釋的方法必須遵守以下所有標(biāo)準(zhǔn):該方法不得有任何參數(shù),除非是在 EJB 攔截器 (interceptor) 的情況下,根據(jù) EJB 規(guī)范的定義,在這種情況下它將帶有一個(gè) InvocationContext 對(duì)象 ;該方法的返回類型必須為 void;該方法不得拋出已檢查異常;應(yīng)用 PostConstruct 的方法可以是 public、protected、package private 或 private;除了應(yīng)用程序客戶端之外,該方法不能是 static;該方法可以是 final;如果該方法拋出未檢查異常,那么不得將類放入服務(wù)中,除非是能夠處理異常并可從中恢復(fù)的 EJB。

特點(diǎn):

1、只有一個(gè)非靜態(tài)方法能使用此注解

2、被注解的方法不得有任何參數(shù)

3、被注解的方法返回值必須為void

4、被注解方法不得拋出已檢查異常

5、此方法只會(huì)被執(zhí)行一次

servlet執(zhí)行流程

注意事項(xiàng)

使用此注解時(shí)會(huì)影響服務(wù)啟動(dòng)時(shí)間。服務(wù)啟動(dòng)時(shí)會(huì)掃描WEB-INF/classes的所有文件和WEB-INF/lib下的所有jar包。

@PostConstruct注解的用法

@PostConstruct是java5的時(shí)候引入的注解,指的是在項(xiàng)目啟動(dòng)的時(shí)候執(zhí)行這個(gè)方法,也可以理解為在spring容器啟動(dòng)的時(shí)候執(zhí)行,可作為一些數(shù)據(jù)的常規(guī)化加載,比如數(shù)據(jù)字典之類的。

被@PostConstruct修飾的方法會(huì)在服務(wù)器加載Servle的時(shí)候運(yùn)行,并且只會(huì)被服務(wù)器執(zhí)行一次。PostConstruct在構(gòu)造函數(shù)之后執(zhí)行

也就是加載順序

服務(wù)器加載Servlet -> servlet 構(gòu)造函數(shù)的加載 -> postConstruct ->init(init是在service 中的初始化方法. 創(chuàng)建service 時(shí)發(fā)生的事件.) ->Service->destory->predestory->服務(wù)器卸載serlvet

那么問(wèn)題:spring中Constructor、@Autowired、@PostConstruct的順序
Constructor >> @Autowired >> @PostConstruct

依賴注入的字面意思就可以知道,要將對(duì)象p注入到對(duì)象a,那么首先就必須得生成對(duì)象p與對(duì)象a,才能執(zhí)行注入。所以,如果一個(gè)類A中有個(gè)成員變量p被@Autowired注解,那么@Autowired注入是發(fā)生在A的構(gòu)造方法執(zhí)行完之后的。

@PostConstruct應(yīng)用場(chǎng)景:
如果想在生成對(duì)象時(shí)候完成某些初始化操作,而偏偏這些初始化操作又依賴于依賴注入,那么就無(wú)法在構(gòu)造函數(shù)中實(shí)現(xiàn)。為此,可以使用@PostConstruct注解一個(gè)方法來(lái)完成初始化,@PostConstruct注解的方法將會(huì)在依賴注入完成后被自動(dòng)調(diào)用。

@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到一個(gè)很實(shí)用的注解,分享給諸位。

痛點(diǎn)

做過(guò)微信或支付寶支付的童鞋,可能遇到過(guò)這種問(wèn)題,就是填寫支付結(jié)果回調(diào),就是在支付成功之后,支付寶要根據(jù)我們給的地址給我們進(jìn)行通知,通知我們用戶是否支付成功,如果成功我們就要去處理下面相應(yīng)的業(yè)務(wù)邏輯,如果在測(cè)試服務(wù),那么這個(gè)回調(diào)地址我們就需要填寫測(cè)試服務(wù)的,如果發(fā)布到線上那么我們就需要改成線上的地址。

針對(duì)上面的場(chǎng)景,我們一般都會(huì)通過(guò)如下的方式,進(jìn)行一個(gè)動(dòng)態(tài)配置,不需要每次去改,防止出現(xiàn)問(wèn)題。

public class PayTest {@Value("${spring.profiles.active}")private String environment;public Object notify(HttpServletRequest request) {if ("prod".equals(environment)) {// 正式環(huán)境} else if ("test".equals(environment)) {// 測(cè)試環(huán)境}return "SUCCESS";} }

上面的代碼看起來(lái)沒(méi)有一點(diǎn)問(wèn)題,但是身為搬磚的我們咋可能這樣搬,姿勢(shì)不對(duì)呀!

問(wèn)題:

擴(kuò)展性太差,如果這個(gè)參數(shù)我們還需要在別的地方用到,那么我們是不是還要使用@Value的注解獲取一遍,假如有天我們的leader突然說(shuō)嗎,test這個(gè)單詞看著太low了,換個(gè)高端一點(diǎn)的,換成dev,那么我們是不是要把項(xiàng)目中所有的test都要改過(guò)來(lái),如果少還好,要是很多,那我們怕不是涼了。

所以我們能不能將這些配置參數(shù)搞成一個(gè)全局的靜態(tài)變量,這樣的話我們直接飲用就好了,哪怕到時(shí)候真的要改,那我也只需要改動(dòng)一處就好了。

注意大坑

有的朋友可能就比較自信了,那我直接加個(gè)static修飾下不就好了,如果你真是打算這樣做,那你就準(zhǔn)備卷好鋪蓋走人吧。直接加static獲取到的值其實(shí)是一個(gè)null,至于原因,大家復(fù)習(xí)下類以及靜態(tài)變量變量的加載順序。

@PostConstruct注解

那么既然說(shuō)出了問(wèn)題,肯定就有解決方法,不然你以為我跟你玩呢。

首先這個(gè)注解是由Java提供的,它用來(lái)修飾一個(gè)非靜態(tài)的void方法。它會(huì)在服務(wù)器加載Servlet的時(shí)候運(yùn)行,并且只運(yùn)行一次

改造:

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

結(jié)果:

我們可以看到在項(xiàng)目啟動(dòng)的時(shí)候進(jìn)行了初始化

到這里我們已經(jīng)可以拿到當(dāng)前運(yùn)行的環(huán)境是測(cè)試還是正式,這樣就可以做到動(dòng)態(tài)配置

最后想說(shuō)

其實(shí)這個(gè)注解遠(yuǎn)不止這點(diǎn)用處,像我之前寫的Redis工具類,我使用的是RedisTemplate操作Redis,導(dǎo)致寫出來(lái)的方法沒(méi)辦法用static修飾,每次使用Redis工具類只能先注入到容器然后再調(diào)用,使用了這個(gè)注解就可以完美的解決這種尷尬的問(wèn)題。代碼如下。

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);} }

總結(jié)

以上是生活随笔為你收集整理的@PostConstruct注解详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。