自定义spring注解 + 切面实现数据的自动转换

引言:项目中常见的数据导入导出功能,往往涉及字典数据的转换,每段导出代码都实现一遍字典数据转换无疑是重复劳动,一般项目中的解决方案都是通过通用的封装进行处理。这里就以此为例讲一讲spring自定义注解 和 spring切面编程。

注解 @interface

注解根据使用方式可分为以下几种:

分类解释
标记注解(Marker Annotation)简单地用来标记某个类或方法,不需要提供任何参数。例如,@Component、@Service、@Controller等注解用于标记组件。
值注解(Value Annotation)用于指定某个注解需要的参数值。例如,@RequestMapping注解中的value参数用于指定请求的URL路径。
元注解(Meta-Annotation)元注解
注解处理器(Annotation Processor)用于在编译时处理注解,生成相应的代码或进行其他操作。例如,可以编写自定义注解处理器来生成根据注解生成文档、进行代码检查等。

这些使用方式提供了灵活的机制,使得开发人员可以根据需求使用注解来简化配置、增强功能和提高开发效率。在Spring框架中,注解的使用非常广泛,可以用于依赖注入、AOP、事务管理等方面。

元注解

要定义一个自定义的Spring注解,需要使用Java的元注解来标记该注解。元注解是一种用于标记其他注解的注解

注解解释使用
@Target用于指定注解可以应用的元素类型,如类ElementType.TYPE、方法ElementType.METHOD、字段ElementType.FIELD等。
@Retention用于指定注解的生命周期,如源代码、编译时、运行时RetentionPolicy.RUNTIME
@Documented用于指定注解是否包含在Java文档中。
@Inherited用于指定注解是否可以被子类继承。

自定义注解示例:

1. 创建注解

/** 标记EXCEL数据导出的注解
 * description: Excel <br>
 * date: 2024/4/16 16:22 <br>
 * author: Boo <br>
 * version: 1.0 <br>
 */
@Documented
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })  // 指定注解可以用在 类、方法、字段上
@Retention(RetentionPolicy.RUNTIME) // 指定该注解运行时可用
public @interface Excel {

    /**
     * 自定义的属性
     * 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
     */
    public String dictType() default "";

}

2. 使用spring AOP

上面自定义的注解指定了可以用在 类、方法、和字段上

为实现数据的自动转换,我们需要以下几个步骤:

需求分析
1.找到需要转换数据的方法这里使用切面,注解作用在方法上,用于标记"切点"。 注解在这里用作“标记注解”
2.获取它的返回值使用环绕通知,可以获取并处理方法的返回值
3.将返回值进行转换注解作用于返回值的字段(类属性)上,用于标记是否需要进行数据转换,并根据“dictType”属性转换对应的数据。 注解在这里用作“标记注解和值注解”
4.将转换后的值返回切面结束
  • 在service的方法上添加注解 @Excel,声明此方法需要切面处理
	@Override
    @Excel
    public List<BizTestingVo> getTestingList(BizTestingReqVo bizTestingReqVo) {
        return bizLimsInfoMapper.selectList(bizTestingReqVo);
    }
  • 在返回值的类型 BizTestingVo中,给它的字段加上注解,说明字段需要处理
@Data
public class BizTestingVo {
    
    @ExcelProperty("姓名")
    private String name;

    @ExcelProperty("性别")
    @Excel(dictType = "gender") // 说明字段需要处理, 并给注解的“dictType”属性设置了一个值(性别的字典类型)
    private String gender;
    
    @ExcelProperty("创建时间")
    @DateTimeFormat("yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;

    @ExcelIgnore
    private String organizationId;

}
  • 创建切面类

@Component
@Aspect
@Slf4j
public class ExcelAspect {

    @Autowired
    private RemoteDictService dictService;

    /**
     * 只要用到了 Excel 这个注解的,就是目标类
     */
    @Pointcut("@annotation(com.pig4cloud.pigx.lims.framework.annotation.Excel)")
//    这是以前的写法 @Around("execution"(* *..*Service.*Pager(..))")
//   上面这个已经把这个替代掉了 @Pointcut("@execution(* *.*Controller.add())")
    private void MyValid() {
    }

    @Around("MyValid()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        joinPoint.getTarget();

        Object returnValue = joinPoint.proceed(); // 执行目标方法
        if (returnValue == null || !(returnValue instanceof List)){
            return returnValue;
        }
        List<Object> list = (List<Object>) returnValue;
        if (list.size() < 1){
            return returnValue;
        }

        Field[] fields = list.get(0).getClass().getDeclaredFields();
        if (fields == null || fields.length < 1){
            return returnValue;
        }

        for (Object o : list) {
            for (Field field : fields) {
                Excel excel4Field = field.getAnnotation(Excel.class);
                if (excel4Field == null){
                    continue;
                }

                String dictType = excel4Field.dictType();
                if (StrUtil.isNotBlank(dictType)){
                    field.setAccessible(true);
                    field.set(o, getDictLabel(dictType, field.get(o)));
                }
            }
        }
        

        return returnValue;

    }


    public String getDictLabel(String dictType, Object dictValue){
        // TODO 根据字典类型和值获取label
        return "";
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值