在实际开发中,有些业务场景我们不能使用注解@Autowire、@Resource、@Inject等自动注入Bean。在多线程的环境下,我们调用Bean的方法来处理我们的业务数据,但是需要处理的数据资源都是单独的,主要针对需要处理的数据资源属于Bean的成员变量,例如:
@Component("withdrawKHQueryResultExecutor")
public class OnlineWithdrawKHQueryResultExecutor implements Callable<String>{
private ErrorTask errorTask;
@Resource
private IOnlineWithdrawQueryService onlineWithdrawQueryService;
@Resource
private IMerchInfoService merchInfoService;
@Resource
private OnlineWithdrawHandler onlineWithdrawHandler;
@Override
public String call() throws Exception {
String txnId = errorTask.getTxnId();
String finalSts = errorTask.getFinalStatus();
BillBizSimple simple = onlineWithdrawQueryService.queryBillBizSimle(txnId);
MerchInfo merchInfo = merchInfoService.selectByMerchId(simple.getMerchId());
if(FilnalStatusEnum.C_FIRST_POST_FAIL.getValue().equals(finalSts)){
onlineWithdrawHandler.handleFirstPostingFail(simple,merchInfo,errorTask);
}
return "执行成功!";
}
public ErrorTask getErrorTask() {
return errorTask;
}
public void setErrorTask(ErrorTask errorTask) {
this.errorTask = errorTask;
}
}
对于我们来说,errorTask就是需要我们传入的资源,再来看调用的方法代码:
@Component("withdrawKHQueryResultJob")
public class WithdrawKHQueryResultJob {
private static final Logger logger = Logger.getLogger(WithdrawKHQueryResultJob.class);
private static final int FIXED_THREAD_POOL_NUM = 5;
private static ExecutorService threadPool = Executors.newFixedThreadPool(FIXED_THREAD_POOL_NUM);
private static List<String> finalStsList;
@Resource
private IErrorTaskService errorTaskService;
@Resource
private OnlineWithdrawKHQueryResultExecutor withdrawKHQueryResultExecutor;
@Override
public void runJob(String batchDate) throws Exception {
try{
// 计算5分钟之前的时间
Date modTime = DateUtil.getTimeByMinute(-5);
// 查询条件
ErrorTaskExampleExt example = new ErrorTaskExampleExt();
example.createCriteria()
.andFinalStatusIn(finalStsList)
.andModifyTimeGreaterThanOrEqualTo(modTime);
// 总记录数
int totalRecords = errorTaskService.countByExample(example);
logger.info(getJobId()+"本次执行总记录数:" + totalRecords);
final CompletionService<String> completionService = new ExecutorCompletionService<String>(threadPool);
Pager pager = new Pager(totalRecords, Constant.QUERY_DBDATE_PAGE_SIZE);
if(pager.getTotal() > 0){
for (int page = 1,n=pager.getPages(); page <= n; page++) {
example.setStart((page-1)*pager.getPageSize());
example.setLimit(pager.getPageSize());
List<ZbErrorTask> handleList= errorTaskService.selectByExampleByPage(example);
if (!CollectionUtils.isEmpty(handleList)) {
for (int i = 0, m = handleList.size(); i < m; i++) {
ZbErrorTask errorTask = handleList.get(i);
withdrawKHQueryResultExecutor.setErrorTask(errorTask);
Future<String> future = completionService.submit(withdrawKHQueryResultExecutor);
}
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
static{
finalStsList = new ArrayList<String>();
finalStsList.add(FilnalStatusEnum.C_FIRST_POST_FAIL.getValue());
}
}
我们把withdrawKHQueryResultExecutor当做参数进行了执行,这样多线程执行就会出问题,我们知道 spring bean 的作用域,
一般常用的有singleton、prototype看来本例中我们的bean需要使用prototype作用域来处理了。我们获取Spring Bean的方式也需要调整下,目前利用了Spring的IOC来注入,那我们还有另外一个方式来获取Bean,那就是我们需要自己来写一个工具类,需要实现Spring的ApplicationContextAware接口,关于用法网上的讲解很多,自行解决,下面看工具类的代码:
public class SpringContextUtil implements ApplicationContextAware {
@Autowired
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtil.context=applicationContext;
}
public static <T> T getBean(String name, Class<T> requiredType){
return context.getBean(name, requiredType);
}
public static Object getBean(String name){
return context.getBean(name);
}
public static <T> Object getBean(Class<T> requiredType){
return context.getBean(requiredType);
}
public static ApplicationContext getContext() {
return context;
}
public static void setContext(ApplicationContext context) {
SpringContextUtil.context = context;
}
}
这样我们就开始调整程序了,最终的代码程序如下:
@Scope("prototype")
@Component("withdrawKHQueryResultExecutor")
public class OnlineWithdrawKHQueryResultExecutor implements Callable<String>{
private ErrorTask errorTask;
@Resource
private IOnlineWithdrawQueryService onlineWithdrawQueryService;
@Resource
private IMerchInfoService merchInfoService;
@Resource
private OnlineWithdrawHandler onlineWithdrawHandler;
@Override
public String call() throws Exception {
String txnId = errorTask.getTxnId();
String finalSts = errorTask.getFinalStatus();
BillBizSimple simple = onlineWithdrawQueryService.queryBillBizSimle(txnId);
MerchInfo merchInfo = merchInfoService.selectByMerchId(simple.getMerchId());
if(FilnalStatusEnum.C_FIRST_POST_FAIL.getValue().equals(finalSts)){
onlineWithdrawHandler.handleFirstPostingFail(simple,merchInfo,errorOrderTask);
}
return "执行成功!";
}
public ErrorTask getErrorTask() {
return errorTask;
}
public void setErrorTask(ErrorTask errorTask) {
this.errorTask = errorTask;
}
}
@Component("withdrawKHQueryResultJob")
public class WithdrawKHQueryResultJob {
private static final Logger logger = Logger.getLogger(WithdrawKHQueryResultJob.class);
private static final int FIXED_THREAD_POOL_NUM = 5;
private static ExecutorService threadPool = Executors.newFixedThreadPool(FIXED_THREAD_POOL_NUM);
private static List<String> finalStsList;
@Resource
private IErrorTaskService errorTaskService;
@Override
public void runJob(String batchDate) throws Exception {
try{
// 计算5分钟之前的时间
Date modTime = DateUtil.getTimeByMinute(-5);
// 查询条件
ErrorTaskExampleExt example = new ErrorTaskExampleExt();
example.createCriteria()
.andFinalStatusIn(finalStsList)
.andModifyTimeGreaterThanOrEqualTo(modTime);
// 总记录数
int totalRecords = errorTaskService.countByExample(example);
logger.info(getJobId()+"本次执行总记录数:" + totalRecords);
final CompletionService<String> completionService = new ExecutorCompletionService<String>(threadPool);
Pager pager = new Pager(totalRecords, Constant.QUERY_DBDATE_PAGE_SIZE);
if(pager.getTotal() > 0){
for (int page = 1,n=pager.getPages(); page <= n; page++) {
example.setStart((page-1)*pager.getPageSize());
example.setLimit(pager.getPageSize());
List<ZbErrorTask> handleList= errorTaskService.selectByExampleByPage(example);
if (!CollectionUtils.isEmpty(handleList)) {
for (int i = 0, m = handleList.size(); i < m; i++) {
ZbErrorOrderTask errorOrderTask = handleList.get(i);
OnlineWithdrawKHQueryResultExecutor withdrawKHQueryResultExecutor = (OnlineWithdrawKHQueryResultExecutor) SpringContextUtil.getBean("withdrawKHQueryResultExecutor");
withdrawKHQueryResultExecutor.setErrorOrderTask(errorOrderTask);
Future<String> future = completionService.submit(withdrawKHQueryResultExecutor);
}
}
}
}
}catch(Exception e){
e.printStackTrace();
}
}
static{
finalStsList = new ArrayList<String>();
finalStsList.add(FilnalStatusEnum.C_FIRST_POST_FAIL.getValue());
}
}