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

解決Spring在Thread中注入Bean無(wú)效的問(wèn)題

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

在Thread中注入Bean無(wú)效

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

因?yàn)镾pring本身默認(rèn)Bean為單例模式構(gòu)建,同時(shí)是非線程安全的,因此禁止了在Thread子類中的注入行為,因此在Thread中直接注入的bean是null的,會(huì)發(fā)生空指針錯(cuò)誤。

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

錯(cuò)誤的注入方法

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

報(bào)NullpointException。

通過(guò)封裝Thread子類注入

個(gè)人比較推薦這種方法,對(duì)外部代碼的影響較小。

@Controller
public class SomeController{
? ? // 通過(guò)注解注入封裝線程的Bean
? ? @AutoWired
? ? SomeThread someThread;
? ? @ResponseBody
? ? @RequestMapping("test")
? ? String testInjection(){
? ? ? ? // 通過(guò)注入的Bean啟動(dòng)線程
? ? ? ? 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();
? ? ? ? ? ? // 此時(shí)someService已被注入,非null.
? ? ? ? }
? ? }
}

正常調(diào)用someService。

通過(guò)外部引入

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

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

Spring多線程中bean的注入問(wèn)題

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

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

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

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

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

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

@Service
class TestExample{
    //這兩個(gè)為線程所需要的Bean
    @Resource
    TestDao testDao;
    @Resource
    NeedDap needDao;
    public void serviceExecute(){
        //在這里開(kāi)啟線程,執(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了
        }
    }
}

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

相關(guān)文章

最新評(píng)論