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

解決Spring在Thread中注入Bean無效的問題

 更新時間:2022年02月24日 09:41:16   作者:嗡湯圓  
這篇文章主要介紹了解決Spring在Thread中注入Bean無效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

在Thread中注入Bean無效

在Spring項目中,有時需要新開線程完成一些復(fù)雜任務(wù),而線程中可能需要注入一些服務(wù)。而通過Spring注入來管理和使用服務(wù)是較為合理的方式。但是若直接在Thread子類中通過注解方式注入Bean是無效的。

因為Spring本身默認Bean為單例模式構(gòu)建,同時是非線程安全的,因此禁止了在Thread子類中的注入行為,因此在Thread中直接注入的bean是null的,會發(fā)生空指針錯誤。

以下分別列舉錯誤的注入方法和兩種解決方式。

錯誤的注入方法

@Controller
public class SomeController{
? ? @ResponseBody
? ? @RequestMapping("test")
? ? String testInjection(){
? ? ? ? // 直接創(chuàng)建并運行線程
? ? ? ? new SomeThread().start();
? ? }
}
// 直接編寫線程
public SomeThread extends Thread {
? ? @Autowired
? ? SomeService someService;
? ? @Override
? ? public void run(){
? ? ? ? // do something...
? ? ? ? someService.doSomething();
? ? ? ? // 此時 someService實例是null.
? ? }
}

報NullpointException。

通過封裝Thread子類注入

個人比較推薦這種方法,對外部代碼的影響較小。

@Controller
public class SomeController{
? ? // 通過注解注入封裝線程的Bean
? ? @AutoWired
? ? SomeThread someThread;
? ? @ResponseBody
? ? @RequestMapping("test")
? ? String testInjection(){
? ? ? ? // 通過注入的Bean啟動線程
? ? ? ? someThread.execute();
? ? }
}
@Component
public class SomeThread {
? ? // 封裝Bean中注入服務(wù)
? ? @AutoWired
? ? SomeService someService
? ? public void execute() {
? ? ? ? new Worker().start();
? ? }
? ? // 線程內(nèi)部類,Thread或者Runnable均可
? ? private class Worker extends Thread {
? ? ? ? @Override
? ? ? ? public void run() {
? ? ? ? ? ? // do something...
? ? ? ? ? ? SomeThread.this.someService.doSomething();
? ? ? ? ? ? // 此時someService已被注入,非null.
? ? ? ? }
? ? }
}

正常調(diào)用someService。

通過外部引入

即在可以注入的地方先得到可用的實例,在通過Thread子類的構(gòu)造函數(shù)引入。這樣會使得在進行代碼修改時,影響到每個使用Thread子類的代碼,修改工作量大。

@Controller
public class SomeController{
? ? // 通過注解注入Service
? ? @AutoWired
? ? SomeService someService;
? ? @ResponseBody
? ? @RequestMapping("test")
? ? String testInjection(){
? ? ? ? // 通過構(gòu)造函數(shù)從外部引入
? ? ? ? new Worker(someService).start();
? ? }
}
public class SomeThread {
? ? private SomeService someService;
? ? public SomeThread(SomeService someService){
? ? ? ? // 通過構(gòu)造函數(shù)從外部引入
? ? ? ? this.someService ?= someService;
? ? }
? ? @Override
? ? public void run() {
? ? ? ? // do something...
? ? ? ? someService.doSomething();
? ? ? ? // 此時someService非null.
? ? }
}

Spring多線程中bean的注入問題

最近碰到了一個問題,使用SSM框架,在Service層需要另開一個線程,這個線程專門用來做一些操作,并將結(jié)果寫入數(shù)據(jù)庫中。但是在線程中使用@Resource或者@Autowired注入全部為NULL,原來是Spring不能在線程中注入。

網(wǎng)上的主要解決方法有

  • 將需要的Bean作為線程的的構(gòu)造函數(shù)的參數(shù)傳入
  • 使用ApplicationContext.getBean方法來靜態(tài)的獲取Bean

我的線程中所需要的Bean的數(shù)量較多,并且以后還有可能增加或者減少,所以方法1并不適合

我的Spring配置文件并不只一個,而且使用getBean方法需要重新加載一遍所有的Bean,這樣也違反的Spring的IoC,并不是我想要的,所以也不采用方法2

最后確定使用內(nèi)部類的方法,將線程中需要的Bean提前注入好,大致的結(jié)構(gòu)如下:

@Service
class TestExample{
    //這兩個為線程所需要的Bean
    @Resource
    TestDao testDao;
    @Resource
    NeedDap needDao;
    public void serviceExecute(){
        //在這里開啟線程,執(zhí)行操作
        ThreadExample te = new ThreadExample();
        te.start();
    }
    
    //內(nèi)部類
    private class ThreadExample extends Thread{
        public ThreadExample(){
            //也可以在構(gòu)造函數(shù)中傳入?yún)?shù)
        }
        public void run(){
            //這里為線程的操作
            //就可以使用注入之后Bean了
        }
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論