原因就是spring和多線程安全的問題,不讓注入
解決方案有以下幾種
一.變量前綴加static,生成set方法並加上@Resource或者@Autowired
變量前綴加static,生成set方法並加上@Resource或者@Autowired,記住把set方法 static 去掉,否則會拋出 @Resource annotation is not supported on static fields
private static VerificDao verificDao;
@Resource
public void setVerificDao(VerificDao verificDao) {
CheckVoiceVerify.verificDao = verificDao;
}
二.根據spring上下文環境獲取bean
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (SpringContextUtils.applicationContext == null) {
SpringContextUtils.applicationContext = applicationContext;
}
}
/** 獲取applicationContext */
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/** 通過name獲取 Bean */
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
/** 通過class獲取Bean */
public static <T> T getBean(Class<T> clazz) {
return getApplicationContext().getBean(clazz);
}
/** 通過name, 以及Clazz返回指定的Bean */
public static <T> T getBean(String name, Class<T> clazz) {
return getApplicationContext().getBean(name, clazz);
}
/** 是否包含Bean */
public static boolean containsBean(String name) {
return getApplicationContext().containsBean(name);
}
/** 判斷該Bean是否是單例 */
public static boolean isSingleton(String name) {
return getApplicationContext().isSingleton(name);
}
/** 根據類型查找Bean */
public static Class<? extends Object> getType(String name) {
return getApplicationContext().getType(name);
}
}
// AuthUserMapper authUserMapper = (AuthUserMapper) SpringContextUtils.getBean("authUserMapper");
// PrimaryAuthUserMapper primaryAuthUserMapper = (PrimaryAuthUserMapper) SpringContextUtils.getBean("primaryAuthUserMapper");
三. 在啓動這個線程的時候,在這個線程的構造函數中把需要注入的對象傳過去
new Thread(new CheckVoiceVerify(verifyService)).start();
例子:
import com.cqsym.mulmbds.entity.seconedaryentity.AuthUser;
import com.cqsym.mulmbds.mapper.primarymapper.PrimaryAuthUserMapper;
import com.cqsym.mulmbds.mapper.secondarymapper.AuthUserMapper;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
public class CopyTableToTestTableTask extends BaseTask {
private static AuthUserMapper authUserMapper;
private static PrimaryAuthUserMapper primaryAuthUserMapper;
@Autowired
public void setAuthUserMapper(AuthUserMapper authUserMapper) {
CopyTableToTestTableTask.authUserMapper = authUserMapper;
}
@Autowired
public void setPrimaryAuthUserMapper(PrimaryAuthUserMapper primaryAuthUserMapper) {
CopyTableToTestTableTask.primaryAuthUserMapper = primaryAuthUserMapper;
}
@Override
void doTask() {
// AuthUserMapper authUserMapper = (AuthUserMapper) SpringContextUtils.getBean("authUserMapper");
// PrimaryAuthUserMapper primaryAuthUserMapper = (PrimaryAuthUserMapper) SpringContextUtils.getBean("primaryAuthUserMapper");
primaryAuthUserMapper.getAllAuthUser2();
logger.info("primaryAuthUserMapper.getAllAuthUser2 已經被執行");
List<AuthUser> authUserList = authUserMapper.getAllAuthUser2();
logger.info("authUserMapper.getAllAuthUser2 已經被執行");
List<List<AuthUser>> authUserListPartitions = Lists.partition(authUserList,50);
for(List<AuthUser> list : authUserListPartitions) {
for(AuthUser authUser : list) {
logger.info(authUser.toString());
}
logger.info("---------50行中間間隔----------------");
Integer resultInt = primaryAuthUserMapper.submitAuthUser(list);
logger.info("primaryAuthUserMapper.submitAuthUser 已經被執行: " + resultInt);
}
logger.info("數據同步已經執行完成!!!");
}
}
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import com.cqsym.mulmbds.task.CopyTableToTestTableTask;
import com.cqsym.mulmbds.task.FirstJobTask;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
@Bean
public ScheduledExecutorService concurrentTaskScheduler(){
ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(20);
executorService.setCorePoolSize(20);
executorService.setMaximumPoolSize(40);
ThreadFactory threadFactory = new CustomizableThreadFactory("TaskExecutor---");
executorService.setThreadFactory(threadFactory);
executorService.setRejectedExecutionHandler(new ScheduledThreadPoolExecutor.CallerRunsPolicy());
return executorService;
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
//taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
taskRegistrar.setScheduler(concurrentTaskScheduler());
CronTrigger firstCronTrigger = new CronTrigger("0/30 * * * * ?");
FirstJobTask firstJobTask = new FirstJobTask();
taskRegistrar.addTriggerTask(firstJobTask, firstCronTrigger);
CronTrigger copyTableToTestTableTaskCronTrigger = new CronTrigger("1 0/5 * * * ?");
CopyTableToTestTableTask copyTableToTestTableTask= new CopyTableToTestTableTask();
taskRegistrar.addTriggerTask(copyTableToTestTableTask, copyTableToTestTableTaskCronTrigger );
}
}