实现一个线程继承了Thread或实现Runnable接口,想在run方法中使用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值。
2:内部类,这个不多说了,实际上属于绕过去了,我自己认为这样写破坏了结构,也不好维护。
3:构造注入,我认为这个方式最好,注入类依旧被spring管理,代码结构简单清晰。
在线程中提供一个构造方法,比如(注意:public RecvThread(boolean flag, DBmapper dbMapper) ):
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
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 {
在启动线程的地方注入:
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 }