Java异步线程中调用Spring容器中Service和Dao的 Bean,以进行数据库和业务的操作
项目中用到了多线程,但是线程异步操作时无法调用Service层和Dao层的函数,进行数据库的读取,然后就想办法如何往线程中注入Service和Dao层的bean。
摘要
项目中用到了多线程,但是线程异步操作时无法调用Service层和Dao层的函数,进行数据库的读取,然后就想办法如何往异步线程中注入Service和Dao层的bean。
刚开始的思路
之前了解到,根据Spring的特性,Spring容器中的Service层和Dao层的Bean都是单例模式,所以我想在我的NotifyRunable类中设置一个静态字段,把 service层的bean赋值给这个静态字段是不是就可以调用了,进行业务查询和处理。
但是什么时候进行赋值呢?一开始的思路是,Spring是在容器初始化时把每个字段进行注入操作的,所以我就想初始化完吧值赋值给NotifyRunable类的静态字段就可以了,这时候我想到了@PostConstruct这个注解,这个注解可以在某个bean初始化完成后执行注解的方法,于是就有了以下代码,经测试可用。
//service类
@Service
public class DeepServiceImpl implements DeepService {
@Autowired
private PersonDao personDao;
/**
* 初始化时,初始化notify对象
*/
@PostConstruct
public void initDeepface() {
/*这里是关键步骤,通过 ==@PostConstruct== 注解,在service初始化时注入到线程类里面*/
NotifyRunable.setPersonDao(personDao);
}
}
//线程类Runnable
public class NotifyRunable implements Runnable {
private static PersonDao personDao;
@Override
public void run() {
//读取数据库的小明
personDao.get("xiaoming");
}
public static PersonDao getPersonDao() {
return personDao;
}
public static void setPersonDao(PersonDao personDao) {
NotifyRunable.personDao = personDao;
}
}
这就解决了问题,但是后来感觉这样代码的解耦性比较差,NotifyRunable的初始化依赖其它类,自其它类中进行,而且使用静态字段也感觉不太好,于是想了其他方法。
另一种方法
能不能在NotifyRunable自己new的时候在构造函数中赋值赋值呢?答案是:可以!
我们只需要在构造函数中获取Spring 容器的上下文就可以获取到Service和Dao层的Bean实体了。
我们用以下方式获取,这样就可以
public class WechatNotifyRunable implements Runnable {
private final Logger logger = Logger.getLogger(WechatNotifyRunable.class);
private static List<JSONObject> notifyList = new ArrayList<JSONObject>();
private UserInfoDao userInfoDao;
private CheckInOutDao checkInOutDao;
private UserinfoMachinesDao userinfoMachinesDao;
private FaceApplyDao faceApplyDao;
private PersonDao personDao;
private LocalCacheRedisDao localCacheRedisDao;
private MachineDao machineDao;
private static ThreadPoolTaskExecutor jobtaskExecutor;
// 保存上一个personid
public static HashMap<String, Long> lastPersonMap = new HashMap<String, Long>();
// 保存上一个Transactionid
public static HashMap<String, Long> lastTransactionMap = new HashMap<String, Long>();
/**
* 构造函数,初始化dao层对象
*/
public WechatNotifyRunable() {
//获取子容器sevlet, 不能获取父容器root,父容器中不存在service和dao实体bean
ServletRequestAttributes sevletRequestAttributes =
(ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = sevletRequestAttributes.getRequest();
WebApplicationContext servletContext = (WebApplicationContext)
request.getAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
//从容器中获取Dao层Bean
userInfoDao = servletContext.getBean("userInfoDaoImpl",UserInfoDao.class);
localCacheRedisDao = servletContext.getBean(LocalCacheRedisDao.class);
}
@Override
public void run() {
}
}
这里补充一下,在获取Spring容器时遇到了一个问题,容器中不存在这个Bean实体,这个是因为刚开始获取的是Spring的Root容器,而Service和Dao的Bean在Spring MVC的Sevlet容器中,这个到下一集讲。
pringMVC中的RootWebApplicationContext与ServletWebApplicationContext区别
提示错误如下
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type [cn.xdf.wlyy.attendance.dao.PersonDao] is defined
如有哪里理解的不好的或不足之处,欢迎您的指出
每天进步一点点!
更多推荐
所有评论(0)