1、情況描述
使用springboot2多線程,線程類無法實現自動注入需要的bean,解決思路,通過工具類獲取需要的bean
如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
package com.ps.uzkefu.apps.ctilink.handler; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.ps.uzkefu.apps.callcenter.entity.CallRecord; import com.ps.uzkefu.apps.callcenter.service.CallRecordService; import com.ps.uzkefu.apps.ctilink.init.ApplicationContextProvider; import com.ps.uzkefu.apps.ctilink.ommodel.CallCdr; import com.ps.uzkefu.apps.ctilink.ommodel.Cdr; import com.ps.uzkefu.apps.ctilink.rediskey.CdrType; import com.ps.uzkefu.apps.ctilink.rediskey.EventType; import com.ps.uzkefu.apps.ctilink.rediskey.RedisKeyPrefix; import com.ps.uzkefu.apps.oms.account.entity.User; import com.ps.uzkefu.apps.oms.account.service.UserService; import com.ps.uzkefu.util.UUIDUtil; import com.ps.uzkefu.utils.PhoneModel; import com.ps.uzkefu.utils.PhoneUtils; import org.apache.commons.lang.StringUtils; import org.redisson.api.RBucket; import org.redisson.api.RedissonClient; import java.util.Date; import java.util.Objects; /** * Author:ZhuShangJin * Date:2018/6/26 */ public class CdrHandler implements Runnable { public Cdr cdr; //無法自動注入 public RedissonClient redissonClient; //無法自動注入 public UserService userService; //無法自動注入 public CallRecordService callRecordService; public CdrHandler() { //new的時候注入需要的bean this .redissonClient = ApplicationContextProvider.getBean(RedissonClient. class ); this .userService = ApplicationContextProvider.getBean(UserService. class ); this .callRecordService = ApplicationContextProvider.getBean(CallRecordService. class ); } public RedissonClient getRedissonClient() { return redissonClient; } public void setRedissonClient(RedissonClient redissonClient) { this .redissonClient = redissonClient; } public Cdr getCdr() { return cdr; } public void setCdr(Cdr cdr) { this .cdr = cdr; } public UserService getUserService() { return userService; } public void setUserService(UserService userService) { this .userService = userService; } public CallRecordService getCallRecordService() { return callRecordService; } public void setCallRecordService(CallRecordService callRecordService) { this .callRecordService = callRecordService; } @Override public void run() { if ( this .getCdr().getOuter() != null ) { saveOuterCdr(); } else if ( this .getCdr().getVisitor() != null ) { saveVistorCdr(); } } private void saveOuterCdr() { // 外呼 通話結束 CallCdr callCdr = null ; RBucket<CallCdr> bucket = 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( new Date()); callCdr.setTalkLength(Integer.parseInt( this .getCdr().getDuration())); callCdr.setTrunkNum( this .getCdr().getTrunkNumber()); callCdr.setHangupTime( new Date()); callCdr.setRecord( this .getCdr().getRecording()); if (callCdr.getAnsweredTime() == null ){ callCdr.setCallTime(callCdr.getHangupTime()); } else { long time = callCdr.getAnsweredTime().getTime() - callCdr.getRingLength()* 1000 ; callCdr.setCallTime( new Date(time)); } //todo 保存到數據庫 User user = userService.selectOne( new EntityWrapper<User>().eq( "extension" , callCdr.getExtensionNum() + "" )); callCdr.setUserName(user.getUserName()); callCdr.setCorpCode(user.getCorpCode()); callCdr.setCreater(user.getId()); callCdr.setId(UUIDUtil.genUUID()); callCdr.setCreateTime( new Date()); PhoneModel phoneModel = PhoneUtils.getPhoneModel(callCdr.getCustomerPhone()); if (phoneModel != null ) { callCdr.setCustomerCity(phoneModel.getCityName()); callCdr.setCustomerProvince(phoneModel.getProvinceName()); } callCdr.setCallId(System.currentTimeMillis() + "" + callCdr.getCallId()); bucket.set(callCdr); CallRecord callRecord = callCdr; boolean result = callRecordService.insert(callRecord); if (result) { bucket.delete(); } } private void saveVistorCdr() { CallCdr callCdr = null ; RBucket<CallCdr> bucket = 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()); PhoneModel phoneModel = 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())); User user = userService.selectOne( new EntityWrapper<User>().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())) { //用戶在坐席未接來電時 未接來電無錄音 掛機 int ringLength = ( int ) (( new Date().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())); } } else if (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 ); int ringLength = ( int ) (( new Date().getTime() - callCdr.getCallTime().getTime())/ 1000 ); callCdr.setRingLength(ringLength); } callCdr.setCreateTime( new Date()); callCdr.setHangupTime( new Date()); 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())) { } else if (Objects.equals(CdrType.UNUSUAL,callCdr.getLastEvent())){ } else { CallRecord callRecord = callCdr; boolean result = callRecordService.insert(callRecord); if (result) { bucket.delete(); } } } } |
2、獲取bean的工具類
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
package com.ps.uzkefu.apps.ctilink.init; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; /** * Author:ZhuShangJin * Date:2018/7/3 */ @Component public class ApplicationContextProvider implements ApplicationContextAware { /** * 上下文對象實例 */ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this .applicationContext = applicationContext; } /** * 獲取applicationContext * * @return */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 通過name獲取 Bean. * * @param name * @return */ public static Object getBean(String name) { return getApplicationContext().getBean(name); } /** * 通過class獲取Bean. * * @param clazz * @param <T> * @return */ public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } /** * 通過name,以及Clazz返回指定的Bean * * @param name * @param clazz * @param <T> * @return */ public static <T> T getBean(String name, Class<T> clazz) { return getApplicationContext().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的值注入了進來。示例代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
/** * *@Description: 關于Spring/SpringBoot在靜態工具類中注入Service的解決方案 *@ClassName: XXUtils.java *@author ChenYongJia *@Date 2019年6月26日 晚上21:20 *@Email [email protected] */ @Component public class XXUtils { @Autowired private SpecialLogSevice sevice; private static SpecialLogSevice specialLogSevice; @PostConstruct public void init() { specialLogSevice = sevice; } //下面的內容就省略了,需要調用specialLogSevice打點就行了 } |
在上述代碼中@PostConstruct是Java EE5規范之后,Servlet新增的兩個影響servlet聲明周期的注解之一,另外一個是@PreConstruct。這兩個都可以用來修飾一個非靜態的返回值為void的方法,并且該方法不能拋出異常。
被@PostConstruct注解修飾的方法會在服務器加載Servlet的時候運行,并且只會被服務器調用一次,類似于Servlet中的init方法。被該注解修飾的方法會在構造器執行之后,init方法執行之前執行。Spring中允許開發者在受理的Bean中去使用它,當IOC容器被實例化管理當前bean時,被該注解修飾的方法會執行,完成一些初始化的工作。
被PreConstruct注解修飾的方法會在服務器卸載Servlet的時候運行,類似于Servlet中的destroy方法。被該注解修飾的方法會在destroy方法執行之后,Servlet徹底卸載之前執行。
到這里:關于Spring/SpringBoot在靜態工具類中注入Service的解決方案!分享完畢了,快去試試吧!希望大家多多支持服務器之家!
原文鏈接:https://blog.csdn.net/zsj777/article/details/80965081