美文网首页
注解aop实战

注解aop实战

作者: 快点给我想个名 | 来源:发表于2020-06-08 19:02 被阅读0次

场景

在一数据库里有几张表,需要在触发字段更新的时候记录下来操作人和更新字段前后的值。不依赖MQ和监听binlog,直接自定义注解,基于AOP功能实现。最简单版本

实现

  • 定义注解
@Target({ METHOD })
@Retention(RUNTIME)
public @interface RecordUpdate {

    /**
     * 对应表名
     * @return
     */
    String tableName();

    /**
     * 处理类
     * @return
     */
    Class<? extends UpdateAspectHandler> handler();

    /**
     * 表对应实体参数位置
     * @return
     */
    int tableEntityIndex();

    /**
     * 操作人ID参数位置
     * @return
     */
    int operatorIdIndex();
    /**
     * 操作人类型参数位置
     * @return
     */
    int operatorTypeIndex();
}
  • 定义切面
@Aspect
@Component
public abstract class UpdateAspectHandler implements ApplicationContextAware {

    private static Logger logger = LoggerFactory.getLogger(UpdateAspectHandler.class);

    private ApplicationContext applicationContext;


    @Before(value = "execution(public * com.simon.dataplatform..*(..)) && @annotation(com.simon.dataplatform.userprofile.annotation.RecordUpdate)")
    public void before(JoinPoint joinPoint) throws NoSuchMethodException {

        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        // 获取方法
        Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
        // 获取参数
        Object[] args = joinPoint.getArgs();
        // 获取注解
        RecordUpdate recordUpdate = method.getAnnotation(RecordUpdate.class);
        if(ObjectUtil.isNull(recordUpdate)) {
            return;
        }

        // 获取参数
        String tableName = recordUpdate.tableName();
        Object operatorId = args[recordUpdate.operatorIdIndex()];
        Object operatorType = args[recordUpdate.operatorTypeIndex()];
        Object tableEntity = args[recordUpdate.tableEntityIndex()];

        try {
            // 获取处理类代理对象
            UpdateAspectHandler updateAspectHandler = applicationContext.getBean(recordUpdate.handler());
            updateAspectHandler.processBefore(tableName,tableEntity,operatorId,operatorType);
        } catch (Exception e) {
            logger.info("UpdateAspectHandler.before tableName:{},operatorId:{},operatorType:{},tableEntity:{}",tableEntity,operatorId,operatorType, JSON.toJSON(tableEntity));
            logger.error("UpdateAspectHandler.before error:{}",e);
        }
    }

    /**
     * 交由具体实现类处理
     * @param tableName 表名
     * @param tableEntity 表对应实体
     * @param operatorId 操作人ID
     * @param operatorType 操作人类型
     */
    public abstract void processBefore(String tableName,Object tableEntity, Object operatorId, Object operatorType);

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
  • 定义UserBaseExt表对应的处理类
@Component
public class UserBaseExtAspectHandler extends UpdateAspectHandler {

    @Resource(name = "userBaseExtService")
    private UserBaseExtService userBaseExtService;

    @Resource(name = "userUpdateLogService")
    private UserUpdateLogService userUpdateLogService;
    
     /**
     * 忽略的属性字段
     */
    private List<String> ignoreFieldList = Arrays.asList("id,update_time,add_time".split(","));
    

    @Override
    public void processBefore(String tableName, Object tableEntity, Object operatorId, Object operatorType) {
        UserBaseExt afterUserBaseExt = (UserBaseExt) tableEntity;

        UserBaseExt beforeUserBaseExt = userBaseExtService.findByStuId(afterUserBaseExt.getStuId());
        if(ObjectUtil.isNull(beforeUserBaseExt)) {
            return;
        }

        Date date = new Date();
        Field[] fields = ReflectUtil.getFields(UserBaseExt.class);
        List<UserUpdateLog> userUpdateLogList = new ArrayList<>(fields.length);
        for (Field field : fields) {
            // 驼峰转蛇形工具类:实体userName,数据库user_name
            String fieldName = ConvFieldNameUtil.camelToUnderline(field.getName());
            
            if(ignoreFieldList.contains(fieldName) || Modifier.isStatic(field.getModifiers())){
                continue;
            }

            Object afterValue = ReflectUtil.getFieldValue(afterUserBaseExt, field);
            // null值底层不更新
            Object afterValue = ReflectUtil.getFieldValue(after, field);
            if(ObjectUtil.isNull(afterValue)){
                continue;
            }
            
            Object beforeValue = ReflectUtil.getFieldValue(beforeUserBaseExt,field);

            if(!ObjectUtil.equal(afterValue,beforeValue)) {
                UserUpdateLog userUpdateLog = new UserUpdateLog();
                userUpdateLog.setStuId(afterUserBaseExt.getStuId());
                userUpdateLog.setOperatorId(Long.valueOf(String.valueOf(operatorId)));
                userUpdateLog.setOperatorType(String.valueOf(operatorType));
                userUpdateLog.setTableName(tableName);
                userUpdateLog.setUpdateTime(date);
                userUpdateLog.setFieldName(field.getName());
                // 对于过长字符串进行截取
                userUpdateLog.setBeforeValue(StrUtil.sub(beforeValue+"",0,128));
                userUpdateLog.setAfterValue(StrUtil.sub(afterValue+"",0,128));
                userUpdateLogList.add(userUpdateLog);
            }
        }
        if(CollectionUtil.isNotEmpty(userUpdateLogList)) {
            userUpdateLogService.insertBatch(userUpdateLogList);
        }
    }
}
  • 使用
@Override
@Transactional(readOnly = false,rollbackFor = Exception.class)
@RecordUpdate(tableName = "user_base_ext",handler = UserBaseExtAspectHandler.class,tableEntityIndex = 0,operatorIdIndex = 1,operatorTypeIndex = 2)
public void updateByStuId(UserBaseExt userBaseExt,Long operatorId,String operatorType) {
    userBaseExt.setUpdateTime(new Date());
    userBaseExtDao.updateByStuId(userBaseExt);
}

相关文章

网友评论

      本文标题:注解aop实战

      本文链接:https://www.haomeiwen.com/subject/mzynzhtx.html