使用Spring+springMVC+mybatis框架建立的項目如果需要使用到多線程可能會出現一個問題——無法創建Bean
錯誤代碼一般爲:
Post-processing failed of bean type [class com.ccbupt.checkwork.checkwork.service.impl.CheckworkServiceImpl] failed; nested exception is java.lang.IllegalStateException: @Resource annotation is not supported on static fields
這是因爲spring框架考慮到線程安全的問題,使得@Resource在多線程中被禁用。
不過,有時候需要開線程完成一些小的或者後臺的功能時,我們還是希望能使用到service和dao
這位博主:http://zhenxingluo918.iteye.com/blog/2223761 在這篇文章中使用了4種方法:
1.設置爲靜態
2.在這個線程的構造函數中把service實例傳過去,然後再啓動。如:new MyThread(myService).start()
3.讓service或者dao的實現類實現Runnable這個接口,然後把你的線程的邏輯寫在run方法裏,啓動的時候,直接this.start()就行。注意除了要在service的實現類中實現Runnable接口外,還應該在service接口中繼承Runnable接口。
4.直接new一個實例
我在service層使用了第4種方法直接創建實例。但是在dao層發現,由於使用了mybatis無法直接將mapper實例化,於是只好另闢蹊徑。
這裏參考了博客:http://blog.csdn.net/hujin_forever/article/details/52150632
最後在dao層使用了實現接口ApplicationContextAware的方式,代碼如下
@Component
public class SpringBeanUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
SpringBeanUtils.applicationContext=applicationContext;
}
public static Object getBean(String name) {
return applicationContext.getBean(name);
}
public static T getBean(String name,Class requiredType){
return applicationContext.getBean(name, requiredType);
}
}
然後再Spring-SpringMVC.xml配置中加入該bean:
<bean id="springBeanUtils" class="com.hujin.common.util.SpringBeanUtils"/>最後使用getBean方法直接創建bean實例即可:
private CheckworkMapper checkworkMapper=(CheckworkMapper) SpringBeanUtils.getBean("checkworkMapper");
要注意getBean中的首字母要小寫,以及該類不需要寫@service標籤