自定义注解用于标识商户id、税率类型及分摊启用状态等元数据,应加在cartitem或orderitem领域实体上,通过aop+反射提取信息并路由至对应taxcalculationstrategy实现差异化税率计算。

明确注解目标与作用域
自定义注解不是魔法,它本身不执行逻辑,而是为编译期或运行时提供“标记信号”。在多商户购物车结算中,你需要标记的是某笔订单项归属的商户主体及其对应税率策略,而非直接“扣减税率”。因此注解应聚焦于标识商户ID、税率类型(如免税/简易计税/一般计税)、是否启用分摊等元数据,例如:@MerchantTaxScope(merchantId = "M001", taxType = TaxType.GENERAL, enabled = true)。
在领域模型层嵌入注解并绑定上下文
把注解加在购物车商品项(CartItem)或订单明细(OrderItem)实体类的字段或类级别上,确保它能随业务对象流转到结算链路各环节。比如:
- 加在
CartItem类上:标识整条购物车项按该商户规则处理; - 加在
cartItem.merchantId字段上:配合AOP或反射提取值,动态加载对应税率配置; - 避免加在DTO或VO上——它们通常不参与核心计算,易导致注解丢失或误用。
用AOP+反射驱动差异化税率扣减
定义一个切面(如@Around("@annotation(merchantTaxScope)")),在结算服务的主方法(如calculateFinalAmount())执行前后介入:
- 从目标方法参数中提取带注解的对象,通过反射读取
merchantId和taxType; - 根据商户ID查缓存或配置中心获取该商户生效的税率、起征点、抵扣规则;
- 调用对应的
TaxCalculator实现(如GeneralTaxCalculator、ExemptTaxCalculator),传入子订单金额、成本价、优惠分摊结果等上下文; - 将计算后的税额、含税价、可抵扣进项等结果回写到原始对象,供后续开票、记账模块使用。
隔离关键:靠策略路由,而非注解硬编码逻辑
注解只做“识别”,不做“计算”。真正的隔离靠策略模式+工厂路由:
- 每个
taxType对应一个实现类,统一实现TaxCalculationStrategy接口; - 工厂类根据注解提取的
taxType返回对应策略实例,避免if-else蔓延; - 不同商户即使
taxType相同,也可通过扩展策略参数(如extraConfigKey)加载独立配置,实现细粒度隔离。











