使用AOP和注解对DTO中的字段进行截断——第一次使用AOP和自定义注解的心得

是骚操作,但是为了应对特殊的需求,实现了通过在方法上应用@TruncateString注解,进入AOP,获得第一个参数中的DTO,然后获取DTO中加了@LimitStringLength注解,将字段修改之后返回。

#AOP中要注意的点:

  1. AOP由Spring管理,所以要生效的话需要加上@Component注解
  2. 可以把注解绑定到一个方法上,然后用这个注解的时候就会调用相应的@Around("truncateString()")标注的方法
@Pointcut("@annotation(com.kingstar.ficc.gtms.common.core.annotation.TruncateString)")
    void truncateString() {}
  1. 对于有返回的方法,AOP中的方法需要返回return joinPoint.proceed();不然被AOP拦截的方法返回会为空

自定义注解中要注意的点

  1. public @interface定义了一个注解
  2. 注解中参数用长得像方法一样的接口定义来接收
    int max(),然后如果没有default值,会报错
  3. @Retention
    -RetentionPolicy.SOURCE仅保留在源文件中
    -RetentionPolicy.CLASS保留至Class中,但运行时被丢弃
    -RetentionPolicy.RUNTIME jvm运行时也会使用该注解
  4. @target:注解可以应用的对象,注解不可以用在入参之中,如果要用在入参之中,需要应用在方法上
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LimitStringLength {

    int max() default Integer.MAX_VALUE; // 默认截取长度为最大值

}
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TruncateString {

}
@Aspect
@Component
@Slf4j
public class TruncateStringAOP {


    @Pointcut("@annotation(com.kingstar.ficc.gtms.common.core.annotation.TruncateString)")
    void truncateString() {}


    @Around("truncateString()")
    public static Object getSubString(ProceedingJoinPoint joinPoint) throws Throwable {
        Object arg;
        try {
            arg = joinPoint.getArgs()[0];
        } catch (Exception e) {
            log.error("Failed to get argument from joinPoint", e);
            return joinPoint.proceed();
        }

        Field[] fields;
        try {
        fields = arg.getClass().getDeclaredFields();
        log.info("Truncating strings in object of class {}", arg.getClass().getName());
    } catch (Exception e) {
        log.error("Failed to get fields from object", e);
        return joinPoint.proceed();
        }
        try {
            for (Field field : fields) {
                if (field.isAnnotationPresent(LimitStringLength.class)) {
                    field.setAccessible(true); // 允许访问私有字段
                    String value = (String) field.get(arg);
                    log.info("Truncating field {} with value {}", field.getName(), value);
                    if (value != null && value.length() > field.getAnnotation(LimitStringLength.class).max()) {
                        String truncatedValue = value.substring(0, field.getAnnotation(LimitStringLength.class).max());
                        field.set(arg, truncatedValue);
                        log.info("Truncated value of field {} to {}", field.getName(), truncatedValue);
                    }
                }
            }
        } catch (Exception e) {
            log.error("Failed to truncate string", e);
            return joinPoint.proceed();
        }
        return joinPoint.proceed();
    }
}
posted @ 2024-07-05 18:02  peterzh6  阅读(39)  评论(0)    收藏  举报