spring建立多例
阿新 • • 發佈:2018-12-06
最近遇到一個了問題,簡單的描述一下。 按模組呼叫介面,比如a、b、c、d四個模組每個模組2~3個介面,一筆交易最多四個模組,所以在呼叫時每個模組開啟一個執行緒。那麼問題來了模組執行緒在主執行緒中是通過註解自動注入的(模組執行緒依賴其他的bean,所以不能new),即模組執行緒單例的。 多執行緒環境下,把介面呼叫需要使用到的引數從主執行緒傳到模組執行緒時,雖然在主執行緒中每一次都new一個新的引數,但因為模組執行緒是單例的,所以會有可能產生髒讀的可能性(引數被其他執行緒覆蓋掉了) 明確了問題後,解決方案是什麼呢,當然對應的就是將單例的變成多例的。 通過上網查詢後在模組執行緒的類加上註解 @Scope("prototype") 但是加上這個註解後並沒有用(並不能多例),梳理了一下問題,當我在一個單例的類中通過@Autowired自動裝配時,並不能產生多例的,原因@Autowired自動裝配時,在spring容器中發現這個類的例項就會裝配進取,所以並沒有顯式的建立新的例項。所以並不能在單例中這樣建立多例。
//獲取Spring上下文
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
ThreadModuleA module_A = wac.getBean("threadModuleA", ThreadModuleA.class);
這是一種不依賴於servlet,不需要注入的方式。但是需要注意一點,在伺服器啟動時,Spring容器初始化時,不能通過以下方法獲取Spring 容器。
這樣的話就可以建立多例了。
下面簡單的放一下程式碼
主執行緒
reportBody = new ReportBody();
List<Task<ReportBody>> tasks = new ArrayList<Task<ReportBody>>();
Map<String, Object> map_report = new HashMap<String, Object>();
map_report.put("reportBody", reportBody);
// Body
//獲取Spring上下文
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext ();
if(reportType.contains(CommonEnum.THEMIS_DATA_A.getCode())){
map_report.put("paramsMap_base", paramsMap_base);
//獲取物件,此操作可以獲取多例物件(ThreadModuleA 需要配置@Scope("prototype"))
ThreadModuleA module_A = wac.getBean("threadModuleA", ThreadModuleA.class);
module_A.taskParams(map_report);
tasks.add(module_A);
}
if(reportType.contains(CommonEnum.THEMIS_DATA_B.getCode())){
map_report.put("paramsMap_base", paramsMap_base);
ThreadModuleB module_B = wac.getBean("threadModuleB", ThreadModuleB.class);
module_B.taskParams(map_report);
tasks.add(module_B);
}
if(reportType.contains(CommonEnum.THEMIS_DATA_C.getCode())) {
map_report.put("paramsMap_C", paramsMap_base);
ThreadModuleC module_C = wac.getBean("threadModuleC", ThreadModuleC.class);
module_C.taskParams(map_report);
tasks.add(module_C);
}
if(reportType.contains(CommonEnum.THEMIS_DATA_D.getCode())){
map_report.put("paramsMap_D", paramsMap_base);
ThreadModuleD module_D = wac.getBean("threadModuleD", ThreadModuleD.class);
module_D.taskParams(map_report);
tasks.add(module_D);
}
模組執行緒父類,賦值取值(其中Task繼承了Callable)
public abstract class RunTask<T> implements Task<T>{
//傳入引數
private Map<String, Object> params;
@Override
public void taskParams(Map<String, Object> params) {
this.params = params;
}
public Map<String, Object> getParams() {
return params;
}
}
模組執行緒
@Component
@Scope(“prototype”)
public class ThreadModuleA extends RunTask{
// 日誌
private static Logger logger = LoggerFactory.getLogger(ThreadModuleA.class);
@Override
public ReportBody call() throws Exception {
// 初始化非同步呼叫所需資訊
//獲取引數
Map<String, Object> map = this.getParams();
return reportBody;
}
}