亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

解決SpringBoot項目使用多線程處理任務時無法通過@Autowired注入bean問題

2024-07-14 08:42:13
字體:
來源:轉載
供稿:網友

最近在做一個“溫濕度控制”的項目,項目要求通過用戶設定的溫濕度數值和實時采集到的數值進行比對分析,因為數據的對比與分析是一個通過前端頁面控制的定時任務,經理要求在用戶開啟定時任務時,單獨開啟一個線程進行數據的對比分析,并將采集到的溫濕度數值存入數據庫中的歷史數據表,按照我們正常的邏輯應該是用戶在請求開啟定時任務時,前端頁面通過調用后端接口,創建一個新的線程來執行定時任務,然后在線程類中使用 @Autowired 注解注入保存歷史數據的service層,在線程類中調用service層保存歷史數據的方法實現溫濕度數據的保存,這時就出現了一個很尷尬的問題,在新開啟的線程中使用 @Autowired 注解無法注入需要的bean(即:保存歷史數據的service層),程序一直在報 NullPointerException 。

這是controller層,方法 startExperiment 和 stopExperiment 分別是開始定時任務和停止定時任務的方法,getData方法不屬于本次討論范圍,不用管

package com.backstage.controller;import com.alibaba.fastjson.JSONObject;import com.backstage.entity.JsonResponse;import com.backstage.entity.Threshold;import com.backstage.service.MainPageService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;/** * @ProjectName: * @Package: com.backstage.controller * @ClassName: MainPageController * @Description: 主頁面相關操作控制器 * @Author: wangzhilong * @CreateDate: 2018/8/29 9:49 * @Version: 1.0 */@RestController@RequestMapping("/main")public class MainPageController { @Autowired private MainPageService mainPageService; /**  * 開始實驗  *  * @param threshold  */ @RequestMapping("/startExperiment") public JsonResponse startExperiment(HttpServletRequest request, Threshold threshold) {  return mainPageService.startExperiment(request, threshold); } /**  * 停止實驗  */ @RequestMapping("/stopExperiment") public JsonResponse stopExperiment() {  return mainPageService.stopExperiment(); } /**  * 獲取實時數據  *  * @return  */ @RequestMapping("/getData") public JSONObject getData() {  return null; }}

 service 層接口代碼,沒什么好說的,直接上代碼:

package com.backstage.service;import com.alibaba.fastjson.JSONObject;import com.backstage.entity.JsonResponse;import com.backstage.entity.Threshold;import javax.servlet.http.HttpServletRequest;/** * @ProjectName:  * @Package: com.backstage.service * @ClassName: MainPageService * @Description: 主頁面相關操作業務層接口 * @Author: wangzhilong * @CreateDate: 2018/8/29 9:51 * @Version: 1.0 */public interface MainPageService { /**  * 開始實驗  *  * @param threshold  */ JsonResponse startExperiment(HttpServletRequest request, Threshold threshold); /**  * 停止實驗  */ JsonResponse stopExperiment(); /**  * 獲取實時數據  *  * @return  */ JSONObject getData();}

 

 service 層實現類代碼,關于springboot項目使用多線程進行業務處理不屬于本章節的討論范圍,如有需要,請留言,我會在看到留言后第一時間更新相關技術文章,由于這里刪除了一些與本章節無關的代碼,如果復制到開發工具內有報錯問題,麻煩大家提醒我一下,以便修改,非常感謝

package com.backstage.service.impl;import com.alibaba.fastjson.JSONObject;import com.backstage.entity.*;import com.backstage.monitor.TimingMonitoring;import com.backstage.service.*;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.scheduling.Trigger;import org.springframework.scheduling.TriggerContext;import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;import org.springframework.scheduling.support.CronTrigger;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletRequest;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;import java.util.concurrent.ScheduledFuture;/** * @ProjectName:  * @Package: com.backstage.service.impl * @ClassName: MainPageServiceImpl * @Description: 主頁面相關操作業務層實現類 * @Author: wangzhilong * @CreateDate: 2018/8/29 9:51 * @Version: 1.0 */@Servicepublic class MainPageServiceImpl implements MainPageService { @Autowired private ThreadPoolTaskScheduler threadPoolTaskScheduler; private ScheduledFuture<?> future2; @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler() {  return new ThreadPoolTaskScheduler(); } /**  * 開始實驗  *  * @param threshold  */ @Override public JsonResponse startExperiment(HttpServletRequest request, Threshold threshold) {  TimingMonitoring timingMonitoring = new TimingMonitoring();  timingMonitoring.setThreshold(threshold, list, experiment.getId(), experimentData.getId());  future2 = threadPoolTaskScheduler.schedule(new TimingMonitoring(), new Trigger() {   @Override   public Date nextExecutionTime(TriggerContext triggerContext) {    //設置定時任務的執行時間為3秒鐘執行一次    return new CronTrigger("0/10 * * * * ?").nextExecutionTime(triggerContext);   }  });  return new JsonResponse(0,"開始實驗!"); } /**  * 停止實驗  */ @Override public JsonResponse stopExperiment() {  if (future2 != null) {   experimentService.upd(getTime());   future2.cancel(true);  }  return new JsonResponse(0,"結束實驗!"); } /**  * 獲取實時數據  *  * @return  */ @Override public JSONObject getData() {  return null; } protected String getTime() {  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  return format.format(new Date()); }}

重點,線程類代碼,大家注意看,我在代碼最開始使用了spring的 @Autowired 注解注入需要的service,可在調用service中的add方法時,程序報空指針異常,一直認為是add方法或者sql語句有問題,找了一上午,也沒發現任何問題,后來單獨調用這個add方法是可以正常插入數據的,唯獨在這個線程類中調用時報錯,感覺和線程有莫大的關系,百度一搜,還真找到了,原來,在線程中為了線程安全,是防注入的,沒辦法,要用到這個類啊。只能從bean工廠里拿個實例了,繼續往下看

package com.backstage.monitor;import com.backstage.entity.DetailedData;import com.backstage.entity.Threshold;import com.backstage.entity.ValveValue;import com.backstage.service.DetailedDataService;import java.text.SimpleDateFormat;import java.util.Date;import java.util.List;/** * @ProjectName: * @Package: com.backstage.monitor * @ClassName: TimingMonitoring * @Description: 定時監測溫(濕)度 數據 * @Author: wangzhilong * @CreateDate: 2018/8/29 10:11 * @Version: 1.0 */public class TimingMonitoring implements Runnable{ //歷史數據業務層接口 @Autowired public DetailedDataService detailedDataService; private Threshold threshold;   //閾值實體類 private List<ValveValue> settingData; //設定的溫濕度數據 private Integer id;      //實驗記錄id private Integer dataId;     //歷史數據主表id public void setThreshold(Threshold threshold, List<ValveValue> settingData, Integer id, Integer dataId) {  this.threshold = threshold;  this.settingData = settingData;  this.id = id;  this.dataId = dataId; } @Override public void run() {  //模擬從PLC獲取到的數據  String data = "001,50.5,002,37,003,45.6,004,40,005,55.2,006,58";  if (data == null || data.trim() == "") {   return; //若獲取到的數據為空,則直接停止該方法的執行  }  double temperature = 0.0; //溫度  double humidity = 0.0;  //濕度  Integer type = null;    //數據類型,1是溫度,2是濕度  //解析數據,并將數據保存到歷史數據數據庫  String[] str = data.split(",");  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS");  for (int i = 0; i < str.length; i++) {   if (i == 1 || i == 5 || i == 9) { //溫度    type = 1;    temperature += Double.parseDouble(str[i]);    //System.out.println("溫度" + i + " -》 " + str[i-1] + ":" + str[i]);    detailedDataService.add(new DetailedData(null, type, Double.parseDouble(str[i]), format.format(new Date()), str[i - 1], dataId));   }   if (i == 3 || i == 7 || i == 11) { //濕度    type = 2;    humidity += Double.parseDouble(str[i]);    //System.out.println("濕度" + i + " -》 " + str[i-1] + ":" + str[i]);    detailedDataService.add(new DetailedData(null, type, Double.parseDouble(str[i]), format.format(new Date()), str[i - 1], dataId));   }  } } /**  * 獲取當前時間,精確到毫秒  * @return  */ protected String getTime() {  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SS");  return format.format(new Date()); }}

獲取bean對象的工具類,既然程序無法通過注解拿到需要的bean,那就只好自己寫個工具類來獲取嘍,下面是工具類代碼

package com.backstage.config;import org.springframework.beans.BeansException;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;/** * @ProjectName: * @Package: com.backstage.config * @ClassName: ApplicationContextProvider * @Description: 獲取bean對象的工具類 * @Author: wangzhilong * @CreateDate: 2018/8/31 13:26 * @Version: 1.0 *//** * Author:ZhuShangJin * Date:2018/7/3 */@Componentpublic class ApplicationContextProvider implements ApplicationContextAware { /**  * 上下文對象實例  */ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  this.applicationContext = applicationContext; } /**  * 獲取applicationContext  *  * @return  */ public static ApplicationContext getApplicationContext() {  return applicationContext; } /**  * 通過name獲取 Bean.  *  * @param name  * @return  */ public static Object getBean(String name) {  return getApplicationContext().getBean(name); } /**  * 通過class獲取Bean.  *  * @param clazz  * @param <T>  * @return  */ public static <T> T getBean(Class<T> clazz) {  return getApplicationContext().getBean(clazz); } /**  * 通過name,以及Clazz返回指定的Bean  *  * @param name  * @param clazz  * @param <T>  * @return  */ public static <T> T getBean(String name, Class<T> clazz) {  return getApplicationContext().getBean(name, clazz); }}

這樣呢,就可以在線程類中寫一個無參的構造方法,在構造方法中,通過調用工具類中的 getBean() 方法就可以拿到實例了,程序在調用這個線程類時,會自動調用其無參的構造方法,在構造方法中我們將需要的bean對象注入,然后就可以正常使用了,下邊是線程類修改后的代碼,由于別的地方沒有改動,所以這里只給大家改動的代碼,省得大家看到一大堆代碼頭疼。

public TimingMonitoring() {  //new的時候注入需要的bean  this.detailedDataService = ApplicationContextProvider.getBean(DetailedDataService.class); }

總結

以上所述是小編給大家介紹的SpringBoot項目使用多線程處理任務時無法通過@Autowired注入bean 問題,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久影视免费观看| 国产亚洲精品91在线| 日韩美女视频在线观看| 久久男人的天堂| 日韩欧美成人网| 国产亚洲a∨片在线观看| 日韩综合中文字幕| 日韩精品在线第一页| 综合久久五月天| 亚洲第一国产精品| 国产精品爱久久久久久久| 日韩女优人人人人射在线视频| 亚洲精品视频在线播放| 91精品久久久久久久久中文字幕| 欧美日韩亚洲高清| 2019中文字幕在线免费观看| 亚洲国产精品视频在线观看| 日韩在线精品一区| 国产精品1区2区在线观看| 91免费观看网站| 日韩av在线免费观看一区| 欧美性生交大片免费| 成人黄色大片在线免费观看| 精品久久久免费| 亚洲欧美一区二区三区情侣bbw| 91久久久久久久久久| 欧美另类xxx| 欧美成人久久久| 亚洲国产精品大全| 91久久久久久| 欧美中文字幕第一页| 成人国产精品一区二区| 亚洲一区中文字幕在线观看| 在线a欧美视频| 日韩av免费观影| 欧美性黄网官网| 午夜精品一区二区三区在线视| 亚洲精品在线看| 国产精品jizz在线观看麻豆| 热99精品只有里视频精品| 亚洲free性xxxx护士白浆| 欧美制服第一页| 久久久久久久国产| 欧美性少妇18aaaa视频| 国产日韩欧美视频在线| 亚洲精品电影久久久| 热门国产精品亚洲第一区在线| 欧美激情第三页| 成人亚洲欧美一区二区三区| 国产偷国产偷亚洲清高网站| 日韩电影大全免费观看2023年上| 精品激情国产视频| 另类天堂视频在线观看| 欧美大片免费看| 久久久亚洲天堂| 国产精品永久免费视频| 亚洲国产精品va在线看黑人动漫| 97超碰色婷婷| 国产精品美女无圣光视频| 国产精品久久久久秋霞鲁丝| 国内精品视频久久| 欧美激情视频在线| 久久激情视频免费观看| 欧日韩不卡在线视频| 欧美亚洲另类在线| 亚洲激情第一页| 亚洲国产精品成人av| 热久久99这里有精品| 午夜精品美女自拍福到在线| 91精品综合视频| 欧美色播在线播放| 日韩av中文字幕在线| 亚洲最大的网站| 日韩欧美aⅴ综合网站发布| 在线精品视频视频中文字幕| 亚洲第一精品福利| 国产精品丝袜久久久久久高清| 欧美性生活大片免费观看网址| 欧美野外猛男的大粗鳮| 国产欧美精品一区二区三区介绍| 国产91精品久久久| 97视频在线免费观看| 美女久久久久久久久久久| 欧美激情精品久久久久| 国产91成人在在线播放| 18久久久久久| 欧美放荡办公室videos4k| 亚洲激情视频网站| 国产这里只有精品| 日本91av在线播放| 亚洲无av在线中文字幕| 一区二区欧美日韩视频| 日韩av电影手机在线| 91手机视频在线观看| 亚洲精品99久久久久中文字幕| 日韩精品视频中文在线观看| 亚洲第一视频网| 欧美精品在线视频观看| 宅男66日本亚洲欧美视频| 欧美有码在线视频| 性欧美xxxx视频在线观看| 中文字幕精品在线| 欧美日韩人人澡狠狠躁视频| 国产一区二区三区高清在线观看| 亚洲天堂av电影| 国产99久久精品一区二区| 色香阁99久久精品久久久| 日韩精品高清视频| 欧美在线激情视频| 91影院在线免费观看视频| 久久久国产精品一区| 6080yy精品一区二区三区| 青青在线视频一区二区三区| 亚洲一区国产精品| 亚洲欧美日韩在线一区| 亚洲网站在线观看| 久久青草福利网站| 2018日韩中文字幕| 另类天堂视频在线观看| 亚洲国产又黄又爽女人高潮的| 亚洲第一在线视频| 日韩**中文字幕毛片| 国产亚洲精品久久| 日韩毛片中文字幕| www.欧美三级电影.com| 久久视频这里只有精品| 国产视频亚洲精品| 97色在线播放视频| 国产精品福利小视频| 日韩人体视频一二区| 欧美极品欧美精品欧美视频| 在线免费观看羞羞视频一区二区| 日韩精品免费在线播放| 国产精品r级在线| 国产精品国产福利国产秒拍| 国产婷婷色综合av蜜臀av| 一区二区在线视频播放| 精品国产乱码久久久久久虫虫漫画| 中文字幕亚洲国产| 欧美一级黑人aaaaaaa做受| 九九久久久久久久久激情| 国产亚洲一区二区精品| 亚洲欧美一区二区激情| 国产欧美在线看| 欧美超级乱淫片喷水| 91社影院在线观看| 亚洲国产日韩精品在线| 国产97免费视| 欧美自拍视频在线| 俺也去精品视频在线观看| 国产精品视频xxx| 狠狠躁夜夜躁人人爽天天天天97| 亚洲午夜久久久影院| 久久精品91久久久久久再现| 欧美贵妇videos办公室| 在线观看欧美日韩国产| 久久久www成人免费精品| 午夜剧场成人观在线视频免费观看| 亚洲第一男人av| 在线观看视频99| 日本精品一区二区三区在线播放视频| 亚洲天堂网站在线观看视频| 亚洲精品456在线播放狼人| 亚洲激情小视频|