實現一個線程繼承了Thread或實現Runnable接口,想在run方法中使用spring依賴注入(操做數據庫),此時報錯爲空指針,就是說沒有注入進來。web
實驗了幾種方式,分別說一下優缺點。spring
1:寫了工具類,實現ApplicationContextAware接口,作一個經過name獲取實例的方式,代碼以下:數據庫
1 public class SpringUtil implements ApplicationContextAware { 2 3 private static ApplicationContext ctx = null; 4 5 @Override 6 public void setApplicationContext(ApplicationContext applicationContext) 7 throws BeansException { 8 9 if (SpringUtil.ctx == null) { 10 SpringUtil.ctx = applicationContext; 11 } 12 } 13 14 public static ApplicationContext getCtx() { 15 return ctx; 16 } 17 18 public static Object getBean(String name) { 19 return getCtx().getBean(name); 20 } 21 22 23 }
這種方式有個缺陷,須要web容器相應以後纔有值,也就說是懶加載了,線程若是比web容器先響應的時候仍是爲null值。app
2:內部類,這個很少說了,實際上屬於繞過去了,我本身認爲這樣寫破壞告終構,也很差維護。ide
3:構造注入,我認爲這個方式最好,注入類依舊被spring管理,代碼結構簡單清晰。工具
在線程中提供一個構造方法,好比(注意:public RecvThread(boolean flag, DBmapper dbMapper) ):this
1 @Component("RecvThread") 2 public class RecvThread extends Observable implements Runnable { 3 4 private boolean flag; 5 6 private DBmapper dbMapper; 7 8 private QueueModel model; 9 10 private static HashMap<String, String> map = new HashMap<String, String>(); 11 12 public RecvThread() { 13 super(); 14 } 15 16 public RecvThread(boolean flag, DBmapper dbMapper) { 17 this.flag = flag; 18 this.dbMapper = dbMapper; 19 } 20 21 public void ob(){ 22 if(true){ 23 super.setChanged(); 24 } 25 notifyObservers(); 26 } 27 28 @Override 29 public void run() { 30 while (flag) { 31 try {
在啓動線程的地方注入:spa
1 @Component("SystemStartBean") 2 public class SystemStartBean extends SpringBeanAutowiringSupport implements Servlet { 3 4 @Autowired 5 private DBmapper dbMapper; 6 7 @Override 8 public void init(ServletConfig arg0) throws ServletException { 9 10 RecvThread rt = new RecvThread(true, dbMapper); 11 rt.addObserver(new RecvThreadListener()); 12 new Thread(rt).start(); 13 }