使用Spring的applicationContext.getBeansOfType获取到的子类Bean不全,代码如下:
工厂类:
package cn.com.kemai.open.service.submsg;
import cn.com.kemai.open.remote.enums.SubMsgBusinessTypeEnum;
import cn.com.kemai.open.remote.util.ValidUtils;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 微信订阅消息服务工厂
*
* @author leiguoqing
* @date 2022 -2-18 14:00
*/
@Slf4j
@Service
public class WxMaSubMsgServiceFactory implements ApplicationContextAware {
/**
* 策略实现类保存到 Map 中 Key 的前缀
*/
private static final String KEY_PREFIX = "wxMaSubMsgServiceTemplate";
/**
* 用于保存所有策略实现类
*/
private final Map<String, WxMaSubMsgServiceTemplate> wxMaSubMsgServiceTemplateMap = Maps.newConcurrentMap();
/**
* 获取微信订阅消息服务
*
* @param busType the bus type
* @return the wx ma sub msg service
*/
public WxMaSubMsgServiceTemplate getService(SubMsgBusinessTypeEnum busType) {
final WxMaSubMsgServiceTemplate wxMaSubMsgServiceTemplate = wxMaSubMsgServiceTemplateMap.get(KEY_PREFIX + busType.getCode());
ValidUtils.isNull(wxMaSubMsgServiceTemplate, "获取微信订阅消息服务策略异常,请检查订阅消息业务类型");
return wxMaSubMsgServiceTemplate;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// key 默认是以实现类的名称,首字母小写名称
final Map<String, WxMaSubMsgServiceTemplate> templateMap = applicationContext.getBeansOfType(WxMaSubMsgServiceTemplate.class);
if (MapUtils.isEmpty(templateMap)) {
return;
}
// 转化为我们自定义的名称
templateMap.values().forEach(templateObj -> {
final Integer code = templateObj.getBusinessType().getCode();
log.info("WxMaSubMsgService BusinessType code = {}", code);
wxMaSubMsgServiceTemplateMap.put(KEY_PREFIX + code, templateObj);
});
wxMaSubMsgServiceTemplateMap.forEach((k, v) -> log.info("init WxMaSubMsgService bean success, name = {},bean = {}", k, v.toString()));
}
}
模板父类:
package cn.com.kemai.open.service.submsg;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.com.kemai.open.properties.WxMaSubMsgProperties;
import cn.com.kemai.open.remote.enums.SubMsgBusinessTypeEnum;
import cn.com.kemai.open.service.IMaAccountService;
import cn.com.kemai.open.service.IMaSubMsgSendRecordService;
import cn.com.kemai.open.service.submsg.data.SubMsgData;
import cn.com.kemai.open.util.SpringContextUtils;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxError;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.error.WxMaErrorMsgEnum;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.util.Assert;
import java.util.List;
import java.util.Objects;
/**
* 微信订阅消息服务模板
*
* @author leiguoqing
* @date 2022 -2-18 9:29
*/
@Slf4j
public abstract class WxMaSubMsgServiceTemplate implements SubMsgCallBack {
/**
* 发送订阅消息
*
* @param accountId 微信小程序账户id
* @param businessIds 业务ids
* @param subMsgData 微信订阅消息参数
*/
public final void sendMsg(Long accountId, List<Long> businessIds, SubMsgData subMsgData) {
Assert.notNull(accountId, "accountId must not null");
Assert.notEmpty(businessIds, "businessIds must not null");
Assert.notNull(subMsgData, "subMsgData must not null");
final Boolean enable = getSpringBean(WxMaSubMsgProperties.class).getEnable();
if (!enable) {
return;
}
// 构建 MsgData
final List<WxMaSubscribeMessage.MsgData> msgDatas = this.buildMsgData(subMsgData.getMsgDataValues());
if (CollectionUtils.isEmpty(msgDatas)) {
return;
}
// 构建 WxMaSubscribeMessage
final WxMaSubscribeMessage wxMaSubscribeMessage = this.buildWxMaSubscribeMessage(getSpringBean(IMaAccountService.class).getOpenIdById(accountId), msgDatas);
if (Objects.isNull(wxMaSubscribeMessage)) {
return;
}
// 默认发送成功
WxError wxError = WxError.builder().errorCode(0).errorMsg("成功").build();
// 发送订阅消息
try {
getSpringBean(WxMaService.class).getSubscribeService().sendSubscribeMsg(wxMaSubscribeMessage);
} catch (WxErrorException e) {
wxError = e.getError();
if (wxError.getErrorCode() != WxMaErrorMsgEnum.CODE_43101.getCode()) {
log.error("推送核销订阅消息异常:", e);
}
}
// 保存订阅消息发送记录
getSpringBean(IMaSubMsgSendRecordService.class).saveRecord(accountId, businessIds, wxError, this.getBusinessType());
// 回调
this.callBack(accountId, businessIds);
}
/**
* 获取业务类型
*
* @return the business type
*/
protected abstract SubMsgBusinessTypeEnum getBusinessType();
/**
* 构建 MsgData 参数
* <br/>
* 可以使用 {@link WxMaSubMsgServiceTemplate#newMsgData(String, String)} 方法构建
*
* @param msgDataValues the msg data values
* @return the list
*/
protected abstract List<WxMaSubscribeMessage.MsgData> buildMsgData(List<String> msgDataValues);
/**
* 构建 WxMaSubscribeMessage 参数
*
* @param toUserOpenId the to user open id
* @param msgDatas the msg datas
* @return the wx ma subscribe message
*/
protected abstract WxMaSubscribeMessage buildWxMaSubscribeMessage(String toUserOpenId, List<WxMaSubscribeMessage.MsgData> msgDatas);
/**
* 创建一个 MsgData
*
* @param name the name
* @param value the value
* @return the wx ma subscribe message . msg data
*/
protected final WxMaSubscribeMessage.MsgData newMsgData(String name, String value) {
WxMaSubscribeMessage.MsgData msgData = new WxMaSubscribeMessage.MsgData();
msgData.setName(name);
msgData.setValue(value);
return msgData;
}
private <T> T getSpringBean(Class<T> cls) {
return SpringContextUtils.getBean(cls);
}
}
3个子类:
package cn.com.kemai.open.service.submsg;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.com.kemai.open.constant.SystemConstants;
import cn.com.kemai.open.properties.WxMaSubMsgProperties;
import cn.com.kemai.open.remote.enums.SubMsgBusinessTypeEnum;
import cn.com.kemai.open.service.IMaAccountCouponService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 微信小程序优惠券过期订阅消息服务
*
* @author leiguoqing
* @date 2022 -1-20 11:39
*/
@RequiredArgsConstructor
@Service
public class ExpiredWxMaSubMsgService extends WxMaSubMsgServiceTemplate {
/**
* 微信小程序订阅消息参数配置
*/
private final WxMaSubMsgProperties wxMaSubMsgProperties;
/**
* 小程序账户-门店优惠券关联表
*/
private final IMaAccountCouponService maAccountCouponService;
/**
* 获取业务类型
*
* @return the business type
*/
@Override
protected SubMsgBusinessTypeEnum getBusinessType() {
return SubMsgBusinessTypeEnum.COUPON_EXPIRED;
}
/**
* 构建 MsgData 参数
*
* @param msgDataValues the msg data values
* @return the list
*/
@Override
protected List<WxMaSubscribeMessage.MsgData> buildMsgData(List<String> msgDataValues) {
return IntStream.range(0, msgDataValues.size())
.mapToObj(idx -> super.newMsgData(wxMaSubMsgProperties.getExpiredTempMsgDataNames()[idx], msgDataValues.get(idx)))
.collect(Collectors.toList());
}
/**
* 构建 WxMaSubscribeMessage 参数
*
* @param toUserOpenId the to user open id
* @param msgDatas the msg datas
* @return the wx ma subscribe message
*/
@Override
protected WxMaSubscribeMessage buildWxMaSubscribeMessage(String toUserOpenId, List<WxMaSubscribeMessage.MsgData> msgDatas) {
return WxMaSubscribeMessage.builder()
.templateId(wxMaSubMsgProperties.getExpiredTempId())
.toUser(toUserOpenId)
.page(SystemConstants.WX_MA_SUB_MSG_JUMP_PAGE)
// 消息参数
.data(msgDatas)
.miniprogramState(wxMaSubMsgProperties.getState())
.build();
}
/**
* 发送消息后回调
*
* @param accountId 微信小程序账户id
* @param businessIds 业务ids
*/
@Override
public void callBack(Long accountId, List<Long> businessIds) {
// 修改该优惠券 “是否发送过期订阅通知” 标志
maAccountCouponService.updateBatchSendExpiredSubMsgToTrue(businessIds);
}
}
package cn.com.kemai.open.service.submsg;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.com.kemai.open.constant.SystemConstants;
import cn.com.kemai.open.properties.WxMaSubMsgProperties;
import cn.com.kemai.open.remote.enums.SubMsgBusinessTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 微信小程序到账订阅消息服务
*
* @author leiguoqing
* @date 2022 -1-20 11:39
*/
@RequiredArgsConstructor
@Service
public class ReceiveWxMaSubMsgService extends WxMaSubMsgServiceTemplate {
/**
* 微信小程序订阅消息参数配置
*/
private final WxMaSubMsgProperties wxMaSubMsgProperties;
/**
* 获取业务类型
*
* @return the business type
*/
@Override
protected SubMsgBusinessTypeEnum getBusinessType() {
return SubMsgBusinessTypeEnum.COUPON_RECEIVE;
}
/**
* 构建 MsgData 参数
*
* @param msgDataValues the msg data values
* @return the list
*/
@Override
protected List<WxMaSubscribeMessage.MsgData> buildMsgData(List<String> msgDataValues) {
return IntStream.range(0, msgDataValues.size())
.mapToObj(idx -> super.newMsgData(wxMaSubMsgProperties.getReceiveTempMsgDataNames()[idx], msgDataValues.get(idx)))
.collect(Collectors.toList());
}
/**
* 构建 WxMaSubscribeMessage 参数
*
* @param toUserOpenId the to user open id
* @param msgDatas the msg datas
* @return the wx ma subscribe message
*/
@Override
protected WxMaSubscribeMessage buildWxMaSubscribeMessage(String toUserOpenId, List<WxMaSubscribeMessage.MsgData> msgDatas) {
return WxMaSubscribeMessage.builder()
.templateId(wxMaSubMsgProperties.getReceiveTempId())
.toUser(toUserOpenId)
.page(SystemConstants.WX_MA_SUB_MSG_JUMP_PAGE)
// 消息参数
.data(msgDatas)
.miniprogramState(wxMaSubMsgProperties.getState())
.build();
}
}
package cn.com.kemai.open.service.submsg;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.com.kemai.open.constant.SystemConstants;
import cn.com.kemai.open.properties.WxMaSubMsgProperties;
import cn.com.kemai.open.remote.enums.SubMsgBusinessTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 微信小程序核销订阅消息服务
*
* @author leiguoqing
* @date 2022 -1-20 11:39
*/
@RequiredArgsConstructor
@Service
public class WriteOffWxMaSubMsgService extends WxMaSubMsgServiceTemplate {
/**
* 微信小程序订阅消息参数配置
*/
private final WxMaSubMsgProperties wxMaSubMsgProperties;
/**
* 获取业务类型
*
* @return the business type
*/
@Override
protected SubMsgBusinessTypeEnum getBusinessType() {
return SubMsgBusinessTypeEnum.COUPON_WRITE_OFF;
}
/**
* 构建 MsgData 参数
*
* @param msgDataValues the msg data values
* @return the list
*/
@Override
protected List<WxMaSubscribeMessage.MsgData> buildMsgData(List<String> msgDataValues) {
return IntStream.range(0, msgDataValues.size())
.mapToObj(idx -> super.newMsgData(wxMaSubMsgProperties.getWriteOffTempMsgDataNames()[idx], msgDataValues.get(idx)))
.collect(Collectors.toList());
}
/**
* 构建 WxMaSubscribeMessage 参数
*
* @param toUserOpenId the to user open id
* @param msgDatas the msg datas
* @return the wx ma subscribe message
*/
@Override
protected WxMaSubscribeMessage buildWxMaSubscribeMessage(String toUserOpenId, List<WxMaSubscribeMessage.MsgData> msgDatas) {
return WxMaSubscribeMessage.builder()
.templateId(wxMaSubMsgProperties.getWriteOffTempId())
.toUser(toUserOpenId)
.page(SystemConstants.WX_MA_SUB_MSG_JUMP_PAGE)
// 消息参数
.data(msgDatas)
.miniprogramState(wxMaSubMsgProperties.getState())
.build();
}
}
控制台只输入两个子类,另外一个没有获取到:
2022-03-01 10:55:20,278 INFO main c.c.k.o.s.s.WxMaSubMsgServiceFactory 58 lambda$setApplicationContext$0 ---- WxMaSubMsgService BusinessType code = 1
2022-03-01 10:55:20,279 INFO main c.c.k.o.s.s.WxMaSubMsgServiceFactory 58 lambda$setApplicationContext$0 ---- WxMaSubMsgService BusinessType code = 3
2022-03-01 10:55:20,280 INFO main c.c.k.o.s.s.WxMaSubMsgServiceFactory 62 lambda$setApplicationContext$1 ---- init WxMaSubMsgService bean success, name = wxMaSubMsgServiceTemplate1,bean = cn.com.kemai.open.service.submsg.ReceiveWxMaSubMsgService@6d997b16
2022-03-01 10:55:20,281 INFO main c.c.k.o.s.s.WxMaSubMsgServiceFactory 62 lambda$setApplicationContext$1 ---- init WxMaSubMsgService bean success, name = wxMaSubMsgServiceTemplate3,bean = cn.com.kemai.open.service.submsg.WriteOffWxMaSubMsgService@1f762537