欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時間:2018年09月02日 08:27:42   作者:Bug開發(fā)工程師  
這篇文章主要介紹了SpringBoot項目使用多線程處理任務(wù)時無法通過@Autowired注入bean問題的解決方法,需要的朋友可以參考下

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

這是controller層,方法 startExperiment 和 stopExperiment 分別是開始定時任務(wù)和停止定時任務(wù)的方法,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: 主頁面相關(guān)操作控制器
 * @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();
 }
 /**
  * 獲取實時數(shù)據(jù)
  *
  * @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: 主頁面相關(guān)操作業(yè)務(wù)層接口
 * @Author: wangzhilong
 * @CreateDate: 2018/8/29 9:51
 * @Version: 1.0
 */
public interface MainPageService {
 /**
  * 開始實驗
  *
  * @param threshold
  */
 JsonResponse startExperiment(HttpServletRequest request, Threshold threshold);
 /**
  * 停止實驗
  */
 JsonResponse stopExperiment();
 /**
  * 獲取實時數(shù)據(jù)
  *
  * @return
  */
 JSONObject getData();
}

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

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ù)層實現(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();
 }
 /**
  * 開始實驗
  *
  * @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è)置定時任務(wù)的執(zhí)行時間為3秒鐘執(zhí)行一次
    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,"結(jié)束實驗!");
 }
 /**
  * 獲取實時數(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());
 }
}

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

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: 定時監(jiān)測溫(濕)度 數(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;   //閾值實體類
 private List<ValveValue> settingData; //設(shè)定的溫濕度數(shù)據(jù)
 private Integer id;      //實驗記錄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)前時間,精確到毫秒
  * @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
 */
@Component
public 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);
 }
}

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

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

總結(jié)

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

相關(guān)文章

  • MyBatis中resultType和parameterType和resultMap使用總結(jié)

    MyBatis中resultType和parameterType和resultMap使用總結(jié)

    這篇文章主要介紹了MyBatis中resultType和parameterType和resultMap使用總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • JAVA 區(qū)分集合和數(shù)組

    JAVA 區(qū)分集合和數(shù)組

    這篇文章主要介紹了JAVA如何區(qū)分集合和數(shù)組,文中講解非常細致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • 如何利用Spring把元素解析成BeanDefinition對象

    如何利用Spring把元素解析成BeanDefinition對象

    這篇文章主要介紹了如何利用Spring把元素解析成BeanDefinition對象,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • Python爬蟲之爬取2020女團選秀數(shù)據(jù)

    Python爬蟲之爬取2020女團選秀數(shù)據(jù)

    本文將對比《青春有你2》和《創(chuàng)造營2020》全體小姐姐,鑒于兩個節(jié)目的數(shù)據(jù)采集和處理過程基本相似,在使用Python做數(shù)據(jù)爬蟲采集的章節(jié)中將只以《創(chuàng)造營2020》為例做詳細介紹。感興趣的同學(xué)可以照貓畫虎去實操一下《青春有你2》的數(shù)據(jù)爬蟲采集,需要的朋友可以參考下
    2021-04-04
  • java固定大小隊列的幾種實現(xiàn)方式詳解

    java固定大小隊列的幾種實現(xiàn)方式詳解

    隊列的特點是節(jié)點的排隊次序和出隊次序按入隊時間先后確定,即先入隊者先出隊,后入隊者后出隊,這篇文章主要給大家介紹了關(guān)于java固定大小隊列的幾種實現(xiàn)方式,需要的朋友可以參考下
    2021-07-07
  • Java基礎(chǔ)之toString的序列化 匿名對象 復(fù)雜度精解

    Java基礎(chǔ)之toString的序列化 匿名對象 復(fù)雜度精解

    序列化即為把內(nèi)存中的對象轉(zhuǎn)換為字節(jié)寫入文件或通過網(wǎng)絡(luò)傳輸?shù)竭h端服務(wù)器,本章節(jié)將帶你了解Java toString的序列化 匿名對象 復(fù)雜度,需要的朋友可以參考下
    2021-09-09
  • springAOP中用joinpoint獲取切入點方法的參數(shù)操作

    springAOP中用joinpoint獲取切入點方法的參數(shù)操作

    這篇文章主要介紹了springAOP中用joinpoint獲取切入點方法的參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • java在文件尾部追加內(nèi)容的簡單實例

    java在文件尾部追加內(nèi)容的簡單實例

    下面小編就為大家?guī)硪黄猨ava在文件尾部追加內(nèi)容的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • java數(shù)據(jù)結(jié)構(gòu)和算法之馬踏棋盤算法

    java數(shù)據(jù)結(jié)構(gòu)和算法之馬踏棋盤算法

    這篇文章主要為大家詳細介紹了java數(shù)據(jù)結(jié)構(gòu)和算法之馬踏棋盤算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java報錯Cause: java.sql.SQLException問題解決

    java報錯Cause: java.sql.SQLException問題解決

    本文主要介紹了java報錯Cause: java.sql.SQLException問題解決,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-08-08

最新評論