首先需要知道的是,容器中的组件,也就是你添加了诸如@Component , @Service , @Controller以及@Repository等等注解,在容器启动的时候是会扫描标注这些注解的类创建bean并放入容器中。
如果该类中的成员变量上使用了诸如@Autowired和@Resource注解时,容器将会找对应的bean并注入–依赖注入。
而在多线程实例中使用@Autowired注解有时得不到对象,为什么呢?
线程类实例如下:
@Component public class TestThread extends Thread{ private static final Logger log = LoggerFactory.getLogger(TestThread.class); @Autowired ISysBoundUserExtendDao boundUserExtendDao; @Autowired SysBoundUserMapper boundUserMapper; int pageBegin; int pageEnd; public TestThread( int pageEnd,int pageBegin) { super(); this.pageEnd = pageEnd; this.pageBegin = pageBegin; log.debug("pageBegin : "+pageBegin+" , pageEnd : "+pageEnd); } public TestThread() { super(); } public TestThread(ISysBoundUserExtendDao boundUserExtendDao, SysBoundUserMapper boundUserMapper, int pageEnd, int pageBegin) { super(); this.boundUserExtendDao = boundUserExtendDao; this.boundUserMapper = boundUserMapper; this.pageEnd = pageEnd; this.pageBegin = pageBegin; log.debug("pageBegin : "+pageBegin+" , pageEnd : "+pageEnd); } public void run(){ String result = ""; Integer pageSize=1000; Map<String, Object> queryMap = new HashMap<>(); for(int i=pageBegin;i<pageEnd;i++){ queryMap.put("page", i); queryMap.put("pageSize", pageSize); log.debug("开始获取第"+i+"页用户..."); List<SysBoundUser> boundUserList = boundUserExtendDao.getBoundUserList(queryMap); //... } } }
使用了@Component和@Autowired注解。
此时创建多线程如下:
@RequestMapping(value="checkUser2",produces="application/json;charset=utf-8") @ResponseBody public String checkUser2(){ String result = ""; TestThread testThread1 = new TestThread(4, 3); testThread1.start(); TestThread testThread2 = new TestThread( 5, 4); testThread2.start(); TestThread testThread3 = new TestThread(6, 5); testThread3.start(); TestThread testThread4 = new TestThread(7, 6); testThread4.start(); TestThread testThread5 = new TestThread(8, 7); testThread5.start(); return result; }
会发现,在run()方法中boundUserExtendDao为null!!!
这是因为创建多线程时,是new的对象实例,非容器扫描时自动创建的对象实例!!!而你创建线程的时候并没有传入boundUserExtendDao。
如果获取的是容器创建的TestThread,那么肯定有mapper和dao:
那么如何在多线程中使用boundUserExtendDao呢?
答:创建的时候传入boundUserExtendDao实例!
实例如下,此时run方法中可以正确拿到mapper和dao:
@Controller @RequestMapping("/test") public class TestDataController { private static final Logger log = LoggerFactory.getLogger(TestDataController.class); @Autowired ISysBoundUserExtendDao boundUserExtendDao; @Autowired SysBoundUserMapper boundUserMapper; @RequestMapping(value="checkUser2",produces="application/json;charset=utf-8") @ResponseBody public String checkUser2(){ String result = ""; TestThread testThread1 = new TestThread( boundUserExtendDao, boundUserMapper,4, 3); testThread1.start(); TestThread testThread2 = new TestThread( boundUserExtendDao, boundUserMapper,5, 4); testThread2.start(); TestThread testThread3 = new TestThread(boundUserExtendDao, boundUserMapper, 6, 5); testThread3.start(); TestThread testThread4 = new TestThread(boundUserExtendDao, boundUserMapper, 7, 6); testThread4.start(); TestThread testThread5 = new TestThread(boundUserExtendDao, boundUserMapper, 8, 7); testThread5.start(); return result; }