使用spring的线程池,在调用线程池时,创建的新线程中获取不到已注入的实例,调用方法时会报空指针异常,比如service业务层的方法。
java线程方法如下
运行后通过debug调试,testManager报空指针
public class TestTask implements Callable {
@Autowired
private TestManager testManager;
public TestTask() {
}
@Override
public Object call() throws Exception {
//testManager报错为Null
Test test = testManager.selectById("1");
return true;
}
}
解决方法
方法一 从context中获取bean(SpringBoot实测可行)
将applicationContext作为静态变量,在实现Runnable的接口类中,直接获取静态的applicationContext,从而获取容器下的service实例
public class TestTask implements Callable {
@Autowired
private TestManager testManager = SpringContextHolder.getBean("testManager");
public TestTask() {
}
@Override
public Object call() throws Exception {
Test test = testManager.selectById("1");
return true;
}
}
方法二 通过参数的形式传入
在调用线程的方法中,直接将service作为参数传入线程中
public class Test {
private TestManage testManage;
@Resource(name="TaskQueueExecutor")
private ThreadPoolTaskExecutor executor;
public static void main() {
TestTask testTask = new TestTask(testManage);
//下面可以忽略
FutureTask<Integer> futureTask = new FutureTask<Integer>(testTask);
executor.execute(testTask);
}
}
public class TestTask implements Callable {
private final TestManage testManage;
public TestTask(testManage) {
//作为参数传入
super();
this.testManage = testManage;
}
@Override
public Object call() throws Exception {
Test test = testManager.selectById("1");
return true;
}
}
方法三 spring容器的重新扫描(未进行测试)
通过在线程类里面添加静态化代码块,spring容器重新扫描
public class TestTask implements Callable {
private static TestManage = testManage;
private static ApplicationContext context = null;
static{
context = new ClassPathXmlApplicationContext("classpath:/spring-context*.xml");
testManage = (TestManage) context.getBean("testManage")
}
public TestTask() {
}
@Override
public Object call() throws Exception {
Test test = testManager.selectById("1");
return true;
}
}