package com.stylefeng.guns.core.intercept; import com.stylefeng.guns.modular.system.dao.UserInfoMapper; import com.stylefeng.guns.modular.system.model.UserInfo; import com.stylefeng.guns.modular.system.model.vo.BalanceModifyRecordVo; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; import org.apache.ibatis.plugin.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; import org.springframework.util.ReflectionUtils; import java.lang.reflect.Field; import java.util.*; /** * 用户余额变更拦截器 * @author sky * @version 1.0.0 * @since 2026/7/3 12:03 */ @Slf4j @Component @Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})}) public class BalanceUpdateInterceptor implements Interceptor { @Autowired private ApplicationContext context; private UserInfoMapper getMapper() { return context.getBean(UserInfoMapper.class); } @Override public Object intercept(Invocation invocation) throws Throwable { MappedStatement ms = (MappedStatement) invocation.getArgs()[0]; Object param = invocation.getArgs()[1]; // 获取SQL类型 SqlCommandType sqlCommandType = ms.getSqlCommandType(); if (sqlCommandType != SqlCommandType.UPDATE) { return invocation.proceed(); } BoundSql boundSql = ms.getBoundSql(param); String sql = boundSql.getSql().toLowerCase(); // 只处理 user 表 if (!sql.contains("t_user")) { return invocation.proceed(); } // 关键:先执行前查旧值(需要拿 userId) Map mapValues = extractUserId(param); Long userId = mapValues.get("userId"); if(Objects.isNull(userId)) { return invocation.proceed(); } // 查询旧的用户 UserInfo oldUser = getMapper().selectById(userId); // 执行更新 Object result = invocation.proceed(); // 查新的用户 UserInfo newUser = getMapper().selectById(userId); Long balanceChangeType = mapValues.get("balanceChangeType"); if(Objects.nonNull(balanceChangeType)) { newUser.setBalanceChangeType(balanceChangeType.intValue()); } // 新增余额的变更记录(所有余额的变更记录都需要存) if(Objects.nonNull(oldUser) && Objects.nonNull(newUser)) { BalanceModifyRecordVo recordVo = BalanceModifyRecordVo.convert(oldUser, newUser); Optional.ofNullable(recordVo).ifPresent(getMapper()::insertBalanceModifyRecord); } return result; } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } /** * 获取用户id */ private Map extractUserId(Object param) { Map mapValues = new HashMap<>(); if (param == null) { return mapValues; } // MyBatis ParamMap if (param instanceof Map) { Map map = (Map) param; // 第一种:直接传id try{ Object balanceChangeType = map.get("balanceChangeType"); if (Objects.nonNull(balanceChangeType)) { mapValues.put("balanceChangeType", Long.valueOf(balanceChangeType.toString())); } Object id = map.get("id"); if (Objects.nonNull(id)) { mapValues.put("userId", Long.valueOf(id.toString())); return mapValues; } } catch (Exception e) { // log.error("sql中没有id"); } // 第二种:MyBatis-Plus update(entity, wrapper) Object entity = map.get("param1"); if (entity == null) { entity = map.get("et"); } if (entity != null) { return extractId(entity, mapValues); } } // 直接就是实体 return extractId(param, mapValues); } private Map extractId(Object obj, Map mapValues) { Field field = ReflectionUtils.findField(obj.getClass(), "id"); if (field == null) { return mapValues; } ReflectionUtils.makeAccessible(field); Object value = ReflectionUtils.getField(field, obj); mapValues.put("userId", value == null ? null : Long.valueOf(value.toString())); Field fieldType = ReflectionUtils.findField(obj.getClass(), "balanceChangeType"); if (fieldType == null) { return mapValues; } ReflectionUtils.makeAccessible(fieldType); Object valueType = ReflectionUtils.getField(fieldType, obj); mapValues.put("balanceChangeType", valueType == null ? null : Long.valueOf(valueType.toString())); return mapValues; } }