一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 解決SpringBoot項(xiàng)目使用多線程處理任務(wù)時(shí)無法通過@Autowired注入bean問題

解決SpringBoot項(xiàng)目使用多線程處理任務(wù)時(shí)無法通過@Autowired注入bean問題

2021-05-29 12:27Bug開發(fā)工程師 Java教程

這篇文章主要介紹了SpringBoot項(xiàng)目使用多線程處理任務(wù)時(shí)無法通過@Autowired注入bean問題的解決方法,需要的朋友可以參考下

最近在做一個(gè)“溫濕度控制”的項(xiàng)目,項(xiàng)目要求通過用戶設(shè)定的溫濕度數(shù)值和實(shí)時(shí)采集到的數(shù)值進(jìn)行比對(duì)分析,因?yàn)閿?shù)據(jù)的對(duì)比與分析是一個(gè)通過前端頁面控制的定時(shí)任務(wù),經(jīng)理要求在用戶開啟定時(shí)任務(wù)時(shí),單獨(dú)開啟一個(gè)線程進(jìn)行數(shù)據(jù)的對(duì)比分析,并將采集到的溫濕度數(shù)值存入數(shù)據(jù)庫中的歷史數(shù)據(jù)表,按照我們正常的邏輯應(yīng)該是用戶在請(qǐng)求開啟定時(shí)任務(wù)時(shí),前端頁面通過調(diào)用后端接口,創(chuàng)建一個(gè)新的線程來執(zhí)行定時(shí)任務(wù),然后在線程類中使用 @autowired 注解注入保存歷史數(shù)據(jù)的service層,在線程類中調(diào)用service層保存歷史數(shù)據(jù)的方法實(shí)現(xiàn)溫濕度數(shù)據(jù)的保存,這時(shí)就出現(xiàn)了一個(gè)很尷尬的問題,在新開啟的線程中使用 @autowired 注解無法注入需要的bean(即:保存歷史數(shù)據(jù)的service層),程序一直在報(bào) nullpointerexception

這是controller層,方法 startexperiment 和 stopexperiment 分別是開始定時(shí)任務(wù)和停止定時(shí)任務(wù)的方法,getdata方法不屬于本次討論范圍,不用管

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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: 主頁面相關(guān)操作控制器
 * @author: wangzhilong
 * @createdate: 2018/8/29 9:49
 * @version: 1.0
 */
@restcontroller
@requestmapping("/main")
public class mainpagecontroller {
 @autowired
 private mainpageservice mainpageservice;
 /**
  * 開始實(shí)驗(yàn)
  *
  * @param threshold
  */
 @requestmapping("/startexperiment")
 public jsonresponse startexperiment(httpservletrequest request, threshold threshold) {
  return mainpageservice.startexperiment(request, threshold);
 }
 /**
  * 停止實(shí)驗(yàn)
  */
 @requestmapping("/stopexperiment")
 public jsonresponse stopexperiment() {
  return mainpageservice.stopexperiment();
 }
 /**
  * 獲取實(shí)時(shí)數(shù)據(jù)
  *
  * @return
  */
 @requestmapping("/getdata")
 public jsonobject getdata() {
  return null;
 }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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: 主頁面相關(guān)操作業(yè)務(wù)層接口
 * @author: wangzhilong
 * @createdate: 2018/8/29 9:51
 * @version: 1.0
 */
public interface mainpageservice {
 /**
  * 開始實(shí)驗(yàn)
  *
  * @param threshold
  */
 jsonresponse startexperiment(httpservletrequest request, threshold threshold);
 /**
  * 停止實(shí)驗(yàn)
  */
 jsonresponse stopexperiment();
 /**
  * 獲取實(shí)時(shí)數(shù)據(jù)
  *
  * @return
  */
 jsonobject getdata();
}

 

 service 層實(shí)現(xiàn)類代碼,關(guān)于springboot項(xiàng)目使用多線程進(jìn)行業(yè)務(wù)處理不屬于本章節(jié)的討論范圍,如有需要,請(qǐng)留言,我會(huì)在看到留言后第一時(shí)間更新相關(guān)技術(shù)文章,由于這里刪除了一些與本章節(jié)無關(guān)的代碼,如果復(fù)制到開發(fā)工具內(nèi)有報(bào)錯(cuò)問題,麻煩大家提醒我一下,以便修改,非常感謝

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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: 主頁面相關(guān)操作業(yè)務(wù)層實(shí)現(xiàn)類
 * @author: wangzhilong
 * @createdate: 2018/8/29 9:51
 * @version: 1.0
 */
@service
public class mainpageserviceimpl implements mainpageservice {
 @autowired
 private threadpooltaskscheduler threadpooltaskscheduler;
 private scheduledfuture<?> future2;
 @bean
 public threadpooltaskscheduler threadpooltaskscheduler() {
  return new threadpooltaskscheduler();
 }
 /**
  * 開始實(shí)驗(yàn)
  *
  * @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) {
    //設(shè)置定時(shí)任務(wù)的執(zhí)行時(shí)間為3秒鐘執(zhí)行一次
    return new crontrigger("0/10 * * * * ?").nextexecutiontime(triggercontext);
   }
  });
  return new jsonresponse(0,"開始實(shí)驗(yàn)!");
 }
 /**
  * 停止實(shí)驗(yàn)
  */
 @override
 public jsonresponse stopexperiment() {
  if (future2 != null) {
   experimentservice.upd(gettime());
   future2.cancel(true);
  }
  return new jsonresponse(0,"結(jié)束實(shí)驗(yàn)!");
 }
 /**
  * 獲取實(shí)時(shí)數(shù)據(jù)
  *
  * @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());
 }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
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: 定時(shí)監(jiān)測(cè)溫(濕)度 數(shù)據(jù)
 * @author: wangzhilong
 * @createdate: 2018/8/29 10:11
 * @version: 1.0
 */
public class timingmonitoring implements runnable{
 //歷史數(shù)據(jù)業(yè)務(wù)層接口
 @autowired
 public detaileddataservice detaileddataservice;
 private threshold threshold;   //閾值實(shí)體類
 private list<valvevalue> settingdata; //設(shè)定的溫濕度數(shù)據(jù)
 private integer id;      //實(shí)驗(yàn)記錄id
 private integer dataid;     //歷史數(shù)據(jù)主表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獲取到的數(shù)據(jù)
  string data = "001,50.5,002,37,003,45.6,004,40,005,55.2,006,58";
  if (data == null || data.trim() == "") {
   return; //若獲取到的數(shù)據(jù)為空,則直接停止該方法的執(zhí)行
  }
  double temperature = 0.0; //溫度
  double humidity = 0.0//濕度
  integer type = null;    //數(shù)據(jù)類型,1是溫度,2是濕度
  //解析數(shù)據(jù),并將數(shù)據(jù)保存到歷史數(shù)據(jù)數(shù)據(jù)庫
  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));
   }
  }
 }
 /**
  * 獲取當(dāng)前時(shí)間,精確到毫秒
  * @return
  */
 protected string gettime() {
  simpledateformat format = new simpledateformat("yyyy-mm-dd hh:mm:ss:ss");
  return format.format(new date());
 }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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對(duì)象的工具類
 * @author: wangzhilong
 * @createdate: 2018/8/31 13:26
 * @version: 1.0
 */
/**
 * author:zhushangjin
 * date:2018/7/3
 */
@component
public class applicationcontextprovider implements applicationcontextaware {
 /**
  * 上下文對(duì)象實(shí)例
  */
 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);
 }
}

這樣呢,就可以在線程類中寫一個(gè)無參的構(gòu)造方法,在構(gòu)造方法中,通過調(diào)用工具類中的 getbean() 方法就可以拿到實(shí)例了,程序在調(diào)用這個(gè)線程類時(shí),會(huì)自動(dòng)調(diào)用其無參的構(gòu)造方法,在構(gòu)造方法中我們將需要的bean對(duì)象注入,然后就可以正常使用了,下邊是線程類修改后的代碼,由于別的地方?jīng)]有改動(dòng),所以這里只給大家改動(dòng)的代碼,省得大家看到一大堆代碼頭疼。

?
1
2
3
4
public timingmonitoring() {
  //new的時(shí)候注入需要的bean
  this.detaileddataservice = applicationcontextprovider.getbean(detaileddataservice.class);
 }

總結(jié)

以上所述是小編給大家介紹的springboot項(xiàng)目使用多線程處理任務(wù)時(shí)無法通過@autowired注入bean 問題,希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

原文鏈接:https://www.cnblogs.com/xiaolong1996/archive/2018/09/01/9571645.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品亚洲专区一区 | 免费人成在线观看视频播放 | 无码日韩精品一区二区免费 | 免费观看视频在线播放 | 色婷婷狠狠 | 国产在线观看福利 | 日本性生活大片 | 免费视频左左视频 | 91综合精品网站久久 | 韩国甜性涩爱免费观看 | 色人阁图片 | 粉嫩高中生第一次不戴套 | 王淑兰与铁柱全文免费阅读 | 天天综合色天天综合网 | 国产成人精品免费 | 国产美女久久久久 | 国产成人亚洲精品91专区高清 | 成人免费视频在 | 成人国产精品 | 国产人va在线 | 亚洲九九爱 | 美女奶口隐私免费视频网站 | 国产成人精品曰本亚洲78 | 波多野结衣同性系列698 | 农夫69小说小雨与农村老太 | 成人一区二区免费中文字幕 | 日韩专区在线观看 | 哇嘎在线精品视频在线观看 | 99精品热| 成全动漫视频在线观看 | 506rr亚洲欧美 | 狠狠干狠狠插 | 亚洲AV无码A片在线观看蜜桃 | 91插插插插 | 久久精品一卡二卡三卡四卡视频版 | 99九九成人免费视频精品 | 91制片厂制作传媒免费版樱花 | 美女被吸乳得到大胸 | 日本亚洲欧洲高清有码在线播放 | 短篇最污的乱淫伦小说全集 | 亚洲国产欧美另类 |