解决SpringBoot2多线程无法注入的问题
1、情况描述
使用springboot2多线程,线程类无法实现自动注入需要的bean,解决思路,通过工具类获取需要的bean
如下
packagecom.ps.uzkefu.apps.ctilink.handler;
importcom.baomidou.mybatisplus.mapper.EntityWrapper;
importcom.ps.uzkefu.apps.callcenter.entity.CallRecord;
importcom.ps.uzkefu.apps.callcenter.service.CallRecordService;
importcom.ps.uzkefu.apps.ctilink.init.ApplicationContextProvider;
importcom.ps.uzkefu.apps.ctilink.ommodel.CallCdr;
importcom.ps.uzkefu.apps.ctilink.ommodel.Cdr;
importcom.ps.uzkefu.apps.ctilink.rediskey.CdrType;
importcom.ps.uzkefu.apps.ctilink.rediskey.EventType;
importcom.ps.uzkefu.apps.ctilink.rediskey.RedisKeyPrefix;
importcom.ps.uzkefu.apps.oms.account.entity.User;
importcom.ps.uzkefu.apps.oms.account.service.UserService;
importcom.ps.uzkefu.util.UUIDUtil;
importcom.ps.uzkefu.utils.PhoneModel;
importcom.ps.uzkefu.utils.PhoneUtils;
importorg.apache.commons.lang.StringUtils;
importorg.redisson.api.RBucket;
importorg.redisson.api.RedissonClient;
importjava.util.Date;
importjava.util.Objects;
/**
*Author:ZhuShangJin
*Date:2018/6/26
*/
publicclassCdrHandlerimplementsRunnable{
publicCdrcdr;
//无法自动注入
publicRedissonClientredissonClient;
//无法自动注入
publicUserServiceuserService;
//无法自动注入
publicCallRecordServicecallRecordService;
publicCdrHandler(){
//new的时候注入需要的bean
this.redissonClient=ApplicationContextProvider.getBean(RedissonClient.class);
this.userService=ApplicationContextProvider.getBean(UserService.class);
this.callRecordService=ApplicationContextProvider.getBean(CallRecordService.class);
}
publicRedissonClientgetRedissonClient(){
returnredissonClient;
}
publicvoidsetRedissonClient(RedissonClientredissonClient){
this.redissonClient=redissonClient;
}
publicCdrgetCdr(){
returncdr;
}
publicvoidsetCdr(Cdrcdr){
this.cdr=cdr;
}
publicUserServicegetUserService(){
returnuserService;
}
publicvoidsetUserService(UserServiceuserService){
this.userService=userService;
}
publicCallRecordServicegetCallRecordService(){
returncallRecordService;
}
publicvoidsetCallRecordService(CallRecordServicecallRecordService){
this.callRecordService=callRecordService;
}
@Override
publicvoidrun(){
if(this.getCdr().getOuter()!=null){
saveOuterCdr();
}elseif(this.getCdr().getVisitor()!=null){
saveVistorCdr();
}
}
privatevoidsaveOuterCdr(){
//外呼通话结束
CallCdrcallCdr=null;
RBucketbucket=redissonClient.getBucket(RedisKeyPrefix.CALL_OUTER_CDR+this.getCdr().getOuter().getId()+"_"+cdr.getCpn());
callCdr=bucket.get();
callCdr.setRedisKey(RedisKeyPrefix.CALL_OUTER_CDR+this.getCdr().getOuter().getId()+"_"+cdr.getCpn());
callCdr.setLastEvent(EventType.BYE);
callCdr.setLastEventTime(newDate());
callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
callCdr.setTrunkNum(this.getCdr().getTrunkNumber());
callCdr.setHangupTime(newDate());
callCdr.setRecord(this.getCdr().getRecording());
if(callCdr.getAnsweredTime()==null){
callCdr.setCallTime(callCdr.getHangupTime());
}else{
longtime=callCdr.getAnsweredTime().getTime()-callCdr.getRingLength()*1000;
callCdr.setCallTime(newDate(time));
}
//todo保存到数据库
Useruser=userService.selectOne(newEntityWrapper().eq("extension",callCdr.getExtensionNum()+""));
callCdr.setUserName(user.getUserName());
callCdr.setCorpCode(user.getCorpCode());
callCdr.setCreater(user.getId());
callCdr.setId(UUIDUtil.genUUID());
callCdr.setCreateTime(newDate());
PhoneModelphoneModel=PhoneUtils.getPhoneModel(callCdr.getCustomerPhone());
if(phoneModel!=null){
callCdr.setCustomerCity(phoneModel.getCityName());
callCdr.setCustomerProvince(phoneModel.getProvinceName());
}
callCdr.setCallId(System.currentTimeMillis()+""+callCdr.getCallId());
bucket.set(callCdr);
CallRecordcallRecord=callCdr;
booleanresult=callRecordService.insert(callRecord);
if(result){
bucket.delete();
}
}
privatevoidsaveVistorCdr(){
CallCdrcallCdr=null;
RBucketbucket=redissonClient.getBucket(RedisKeyPrefix.CALL_VISITOR_CDR+this.getCdr().getVisitor().getId()+"_"+cdr.getTrunkNumber());
callCdr=bucket.get();
callCdr.setRedisKey(RedisKeyPrefix.CALL_VISITOR_CDR+this.getCdr().getVisitor().getId()+"_"+cdr.getTrunkNumber());
callCdr.setRecord(this.getCdr().getRecording());
PhoneModelphoneModel=PhoneUtils.getPhoneModel(callCdr.getCustomerPhone());
if(phoneModel!=null){
callCdr.setCustomerCity(phoneModel.getCityName());
callCdr.setCustomerProvince(phoneModel.getProvinceName());
}
callCdr.setCallId(System.currentTimeMillis()+""+callCdr.getCallId());
callCdr.setId(UUIDUtil.genUUID());
//来电通话结束外部电话呼入接入分机的童虎记录
if(Objects.equals(CdrType.IN,this.getCdr().getType())&&this.getCdr().getCdpn().length()==5){
callCdr.setExtensionNum(Integer.parseInt(this.getCdr().getCdpn()));
Useruser=userService.selectOne(newEntityWrapper().eq("extension",callCdr.getExtensionNum()+""));
callCdr.setUserName(user.getUserName());
callCdr.setCorpCode(user.getCorpCode());
callCdr.setCreater(user.getId());
if(Objects.equals(EventType.RING,callCdr.getLastEvent())){
if(StringUtils.isBlank(this.getCdr().getRecording())){
//用户在坐席未接来电时未接来电无录音挂机
intringLength=(int)((newDate().getTime()-callCdr.getLastEventTime().getTime())/1000);
callCdr.setRingLength(ringLength);
callCdr.setTalkLength(0);
}else{
//特殊情况坐席接听后立马挂掉
callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
callCdr.setRingLength(-1);
callCdr.setLastEvent(CdrType.UNUSUAL);
}
}else{
//正常情况
callCdr.setTalkLength(Integer.parseInt(this.getCdr().getDuration()));
}
}elseif(Objects.equals(CdrType.IN,this.getCdr().getType())&&this.getCdr().getCdpn().length()!=5){
//客服没接到
callCdr.setExtensionNum(0);
callCdr.setUserName("未接到");
callCdr.setCorpCode(this.getCdr().getCdpn());
callCdr.setCreater("未接到");
callCdr.setTalkLength(0);
intringLength=(int)((newDate().getTime()-callCdr.getCallTime().getTime())/1000);
callCdr.setRingLength(ringLength);
}
callCdr.setCreateTime(newDate());
callCdr.setHangupTime(newDate());
bucket.set(callCdr);
if(Objects.equals(CdrType.IN,this.getCdr().getType())
&&this.getCdr().getCdpn().length()==5
&&Objects.equals(EventType.RING,callCdr.getLastEvent())
&&StringUtils.isNotBlank(this.cdr.getRecording())){
}elseif(Objects.equals(CdrType.UNUSUAL,callCdr.getLastEvent())){
}else{
CallRecordcallRecord=callCdr;
booleanresult=callRecordService.insert(callRecord);
if(result){
bucket.delete();
}
}
}
}
2、获取bean的工具类
packagecom.ps.uzkefu.apps.ctilink.init;
importorg.springframework.beans.BeansException;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.ApplicationContextAware;
importorg.springframework.stereotype.Component;
/**
*Author:ZhuShangJin
*Date:2018/7/3
*/
@Component
publicclassApplicationContextProviderimplementsApplicationContextAware{
/**
*上下文对象实例
*/
privatestaticApplicationContextapplicationContext;
@Override
publicvoidsetApplicationContext(ApplicationContextapplicationContext)throwsBeansException{
this.applicationContext=applicationContext;
}
/**
*获取applicationContext
*
*@return
*/
publicstaticApplicationContextgetApplicationContext(){
returnapplicationContext;
}
/**
*通过name获取Bean.
*
*@paramname
*@return
*/
publicstaticObjectgetBean(Stringname){
returngetApplicationContext().getBean(name);
}
/**
*通过class获取Bean.
*
*@paramclazz
*@param
*@return
*/
publicstaticTgetBean(Classclazz){
returngetApplicationContext().getBean(clazz);
}
/**
*通过name,以及Clazz返回指定的Bean
*
*@paramname
*@paramclazz
*@param
*@return
*/
publicstaticTgetBean(Stringname,Classclazz){
returngetApplicationContext().getBean(name,clazz);
}
}
3、通过工具类的getBean方法即可获取bean
补充知识:关于Spring/SpringBoot在静态工具类中注入Service的解决方案
前言今天博主将为大家分享:关于Spring/SpringBoot在静态工具类中注入Service的解决方案!不喜勿喷,如有异议欢迎讨论!
最近遇到了需要在工具类中注入Service,由于工具类中方法一般都是静态的,所以要求该属性也要是静态的(Service)。但是由于Spring/SpringBoot正常情况下不能支持注入静态属性(会报空指针异常)。主要原因在于:Spring的依赖注入实际上是依赖于Set方法进行注入值的,Spring是基于对象层面的依赖注入,而静态属性/静态变量实际上是属于类的。
解决方案:
给当前的工具类加上@Component,使其成为一个bean对象
声明一个静态的属性(加上注解@Autowired),一个非静态的属性。
声明一个返回值为void并且不能抛出异常的方法,在其中将非静态属性赋值给静态属性。该方法上加上注解@PostConstruct
这样就将service的值注入了进来。示例代码如下:
/**
*
*@Description:关于Spring/SpringBoot在静态工具类中注入Service的解决方案
*@ClassName:XXUtils.java
*@authorChenYongJia
*@Date2019年6月26日晚上21:20
*@Emailchen87647213@163.com
*/
@Component
publicclassXXUtils{
@Autowired
privateSpecialLogSevicesevice;
privatestaticSpecialLogSevicespecialLogSevice;
@PostConstruct
publicvoidinit(){
specialLogSevice=sevice;
}
//下面的内容就省略了,需要调用specialLogSevice打点就行了
}
在上述代码中@PostConstruct是JavaEE5规范之后,Servlet新增的两个影响servlet声明周期的注解之一,另外一个是@PreConstruct。这两个都可以用来修饰一个非静态的返回值为void的方法,并且该方法不能抛出异常。
被@PostConstruct注解修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet中的init方法。被该注解修饰的方法会在构造器执行之后,init方法执行之前执行。Spring中允许开发者在受理的Bean中去使用它,当IOC容器被实例化管理当前bean时,被该注解修饰的方法会执行,完成一些初始化的工作。
被PreConstruct注解修饰的方法会在服务器卸载Servlet的时候运行,类似于Servlet中的destroy方法。被该注解修饰的方法会在destroy方法执行之后,Servlet彻底卸载之前执行。
到这里:关于Spring/SpringBoot在静态工具类中注入Service的解决方案!分享完毕了,快去试试吧!希望大家多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。