修改单例属性引发的血案

8 篇文章 0 订阅
6 篇文章 0 订阅

背景

最近接触的一些系统中遇到一个问题,一个交易的服务对外提供了支付和退款两种能力,但是发现运行时交易的服务走了退款。
原因是spring容器管理的一个对象service 属性运行时被改变,导致上下流程对不上的问题,多业务链路并发时引发运行时属性错乱,导致 支付和退款行为混淆
下面是大体代码样例。记录下问题原因

样例

1、定义一个核心支付服务
public interface CoreService {

    public BaseResult trade(TradeParam tradeParam);
}

2、抽象两个业务单元 验证和执行

public interface TradeService extends CoreService{

    public VerificationService getVerificationService();

    public void setVerificationService(VerificationService VerificationService);

    public OperationService getOperationService();

    public void setOperationService(OperationService OperationService);
}
3、实现共享逻辑代码
@Service
public class TradeServiceImpl implements TradeService{

    private VerificationService verificationService;

    private OperationService operationService;

    @Override
    public VerificationService getVerificationService() {
        return this.operationService;
    }

    @Override
    public void setVerificationService(VerificationService verificationService) {
        this.verificationService=verificationService;
    }

    @Override
    public OperationService getOperationService() {
        return verificationService;
    }

    @Override
    public void setOperationService(OperationService OperationService) {
        this.operationService = operationService;
    }

    @Override
    public BaseResult trade(TradeParam tradeParam) {
        getVerificationService().verification(tradeParam);
        getOperationService().operate(tradeParam);
        return null;
    }
}

4、实现支付链路

public class PayServiceImpl implements CoreService{


    @Autowired
    @Qualifier("payVerificationService")
    private VerificationService payVerificationService;

    @Autowired
    @Qualifier("tradeService")
    private TradeService tradeService;

    @Autowired
    @Qualifier("payOperationService")
    private OperationService payOperationService;


    @Override
    public BaseResult trade(TradeParam tradeParam) {
        tradeService.setVerificationService(payVerificationService);
        tradeService.setOperationService(payOperationService);
        return tradeService.trade(tradeParam);
    }
}

5、实现退款链路
public class RefundServiceImpl implements CoreService{


    @Autowired
    @Qualifier("refundVerificationService")
    private VerificationService refundVerificationService;

    @Autowired
    @Qualifier("tradeService")
    private TradeService tradeService;

    @Autowired
    @Qualifier("refundOperationService")
    private OperationService refundOperationService;


    @Override
    public BaseResult trade(TradeParam tradeParam) {
        tradeService.setVerificationService(refundVerificationService);
        tradeService.setOperationService(refundOperationService);
        return tradeService.trade(tradeParam);
    }
}

经上方案实现落地后, 支付和退款业务并发时就有概率导致支付和退款运行时对应的实际逻辑单元混乱,导致要支付的实际退款,要退款的实际支付的事情发生。 因为tradeService服务是容器管理的单例,多链路并发修改了单例内的属性,导致运行时故障

方案

修改的方式有很多,最终只要保证运行时的节点数据不存在被覆盖的目的即可。
最简单的替换方案就是将两个set值的逻辑类去掉,改为bean初始化时注入,支付和退款各自初始化一个不同的tradeService即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值