问题:项目启动后,Spring在发现线程类的时候,并不会帮线程类主动注入所需的bean(mapper接口和serviceImpl),所以你使用@Autowired注解也是没用的。
解决办法:手动注入
这里需要写一个手动注入bean的工具类:
/**
* @Description: 手动获取Spring中的bean 注意这个类要一定交给spring来管理,注册到spring的配置文件中
* spring-db-context.xml:<bean class="com.xxx.SpringApplicationContextHolder" />
* @Author yunyao.huang
* @Date 2019年3月7日
*/
public class SpringApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
SpringApplicationContextHolder.context = context;
}
public static Object getSpringBean(String beanName) {
if (StringUtils.isNotBlank(beanName)) {
return context==null?null:context.getBean(beanName);
}
return null;
}
public static String[] getBeanDefinitionNames() {
return context.getBeanDefinitionNames();
}
}
注意:这里此工具类一定要交给Spring来管理,在spring配置文件中加入
<bean class="com.xxx.SpringApplicationContextHolder" />
然后就可以手动注入bean了:
// 由于多线程执行的方法,所以这里必须手动注入 CPMapper、MessageProcessMapper,以免空指针
public CommonXMLParseService() {
super();
cpMapper = (CPMapper) SpringApplicationContextHolder.getSpringBean("CPMapper");
messageProcessMapper = (MessageProcessMapper) SpringApplicationContextHolder.getSpringBean("messageProcessMapper");
}
这里注意如果你的mapper 接口的名字不是驼峰命名,例如CPMapper,那你获取bean的默认名是“CPMapper”(跟接口名一致),如果是驼峰命令,那Spring默认起的名字就是类名的首字母小写即可。
这里也注意到了ApplicationContextAware,后面再写个专门ApplicationContextAware的文章