Spring在Thread中注入Bean無效

在Spring項目中,有時須要新開線程完成一些複雜任務,而線程中可能須要注入一些服務。而經過Spring注入來管理和使用服務是較爲合理的方式。可是若直接在Thread子類中經過註解方式注入Bean是無效的。java

由於Spring自己默認Bean爲單例模式構建,同時是非線程安全的,所以禁止了在Thread子類中的注入行爲,所以在Thread中直接注入的bean是null的,會發生空指針錯誤。安全

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

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

報NullpointException。ide

經過封裝Thread子類注入

我的比較推薦這種方法,對外部代碼的影響較小。函數

@Controller
public class SomeController{
    // 經過註解注入封裝線程的Bean
    @AutoWired
    SomeThread someThread;
    @ResponseBody
    @RequestMapping("test")
    String testInjection(){
        // 經過注入的Bean啓動線程
        someThread.execute();
    }
}

@Component
public class SomeThread {
    // 封裝Bean中注入服務
    @AutoWired
    SomeService someService
    public void execute() {
        new Worker().start();
    }
    // 線程內部類,Thread或者Runnable都可
    private class Worker extends Thread {
        @Override
        public void run() {
            // do something...
            SomeThread.this.someService.doSomething();
            // 此時someService已被注入,非null.
        }
    }
}

正常調用someService。this

經過外部引入

即在能夠注入的地方先獲得可用的實例,在經過Thread子類的構造函數引入。這樣會使得在進行代碼修改時,影響到每一個使用Thread子類的代碼,修改工做量大。spa

@Controller
public class SomeController{
    // 經過註解注入Service
    @AutoWired
    SomeService someService;
    @ResponseBody
    @RequestMapping("test")
    String testInjection(){
        // 經過構造函數從外部引入
        new Worker(someService).start();
    }
}

public class SomeThread {
    private SomeService someService;
    public SomeThread(SomeService someService){
        // 經過構造函數從外部引入
        this.someService  = someService;
    }
    @Override
    public void run() {
        // do something...
        someService.doSomething();
        // 此時someService非null.
    }
}
相關文章
相關標籤/搜索