自定义注解进行数据转换

本文介绍了Java注解的基本概念,自定义注解的创建,如何在类上应用@Retention和@Target,以及如何在实体类中使用注解并进行校验处理。实例展示了注解的num属性应用和属性赋值的处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:
Java注解是一种元数据机制,可用于方法,字段,类等程序上以提供关于这些元素的额外信息。
以下内容是我自己写的一个小测试的demo,参考该文章进行编写:https://blog.youkuaiyun.com/m0_71621983/article/details/131816443

1.自定义注解

在这里插入图片描述
注:在该注解中定义了num属性,设置默认值,引用该注解可以对num属性进行额外赋值
属性类型可以是任意类型,字符串,枚举,数值等等…

java.lang.annotation提供了五种元注解:
@Documented – 注解是否将包含在JavaDoc中
@Retention – 什么时候使用该注解
@Target – 注解用于什么地方
@Inherited – 是否允许子类继承该注解
@Repeatable - 是否可重复注解,jdk1.8引入

类上引用了@Target注解,表示这个注解应用到哪个元素上,包含以下范围值:

public enum ElementType {
    /** 类,接口(包括注解类型)或枚举的声明 */
    TYPE,
    /** 属性的声明 */
    FIELD,
    /** 方法的声明 */
    METHOD,
    /** 方法形式参数声明 */
    PARAMETER,
    /** 构造方法的声明 */
    CONSTRUCTOR,
    /** 局部变量声明 */
    LOCAL_VARIABLE,
    /** 注解类型声明 */
    ANNOTATION_TYPE,
    /** 包的声明 */
    PACKAGE,
    /** 类型参数声明(jdk1.8加入) */
    TYPE_PARAMETER,
    /** 任意类型(jdk1.8加入) */
    TYPE_USE
}

@Retention

public enum RetentionPolicy {
    /** 注解将被编译器忽略掉 */
    SOURCE,
    /** 注解将被编译器记录在class文件中,但在运行时不会被虚拟机保留,这是一个默认的行为 */
    CLASS,
    /** 注解将被编译器记录在class文件中,而且在运行时会被虚拟机保留,因此它们能通过反射被读取到 */
    RUNTIME
}

2.创建一个实体类,定义该注解

在这里插入图片描述
以上实体类的属性引用该自定义注解,设置注解的额外值

3.对注解的值进行校验处理

在这里插入图片描述
输出结果:

name名字-输出.num()----------------------
name名字-输出.bean----------------------

codeTab-输出.num()----------------------
new_codeTab-输出.bean--------------------

输出值1:直接输出注解的num值
输出值2:输出field的属性值,该field在此代码中进行了set()方法赋值操作,如果没有set()则输出null

bean的对象属性值[name=“name名字”,number=null,tab=“new_codeTab”]

注:如果代码中没有使用field.set()进行赋值,则bean属性都为null

Field类具体方法的一些用法可以参考这篇文章:https://blog.youkuaiyun.com/yyuggjggg/article/details/126021525

在要使用该注解的地方调用该映射方法,传入要映射的bean对象!在这里插入图片描述

### 自定义注解实现数据字典映射 #### 背景说明 在实际开发过程中,当项目中涉及大量数据字典的配置时,通常会面临代码冗余和可维护性下降的问题。为了提升代码质量并简化逻辑处理流程,可以采用自定义注解的方式配合 AOP 技术完成数据字典的动态映射[^2]。 --- #### 实现原理概述 通过自定义注解结合 AspectJ 或 Spring AOP 的环绕通知机制,可以在方法执行前后拦截目标对象的数据流,并将其按照预设规则进行转换。具体来说: - **自定义注解**:用于标记需要映射的目标字段或实体。 - **切面编程 (AOP)**:利用 `execution` 表达式匹配指定的方法调用路径,在方法返回前对结果集中的特定字段应用字典映射逻辑[^3]。 这种设计模式不仅能够减少重复代码量,还能显著提高系统的扩展性和灵活性。 --- #### 示例代码展示 以下是基于上述理论构建的一个简单案例演示如何使用自定义注解完成数据字典映射操作: ##### 1. 定义自定义注解 创建两个注解分别适用于单个参数以及整个实体类上的场景需求。 ```java import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; // 针对单一属性使用的注解 @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DictItemParam { String dictCode(); // 字典类型编码 } // 针对整体实体类使用的注解 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface DictItemEntity {} ``` ##### 2. 编写切面处理器 下面是一个典型的切面类实现片段,它负责捕获被标注有我们刚才定义好的那些特殊标签的对象实例然后实施相应的替换动作。 ```java import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; @Component @Aspect public class DictionaryMappingAspect { @Around("execution(* com.example.service.*.*(..)) && @annotation(com.example.annotation.DictItemEntity)") public Object mapDictionaryValues(ProceedingJoinPoint joinPoint) throws Throwable { Object result = joinPoint.proceed(); if(result instanceof List){ ((List<?>)result).forEach(item -> processObjectFields(item)); }else{ processObjectFields(result); } return result; } private void processObjectFields(Object object){ Field[] fields = object.getClass().getDeclaredFields(); Arrays.stream(fields).filter(field -> field.isAnnotationPresent(DictItemParam.class)) .forEach(field -> convertFieldToDictValue(object,field)); } private void convertFieldToDictValue(Object obj, Field field){ try { field.setAccessible(true); String dictCode = field.getAnnotation(DictItemParam.class).dictCode(); Object rawValue = field.get(obj); String mappedValue = dictionaryService.lookupByCodeAndKey(dictCode,String.valueOf(rawValue)); field.set(obj,mappedValue); } catch(Exception e){ throw new RuntimeException(e.getMessage(),e); } } } ``` > 注:此处假设存在名为 `dictionaryService` 的服务组件提供查找对应关系的功能接口 `lookupByCodeAndKey(String code, String key)` 来获取最终显示名称[^4]。 --- #### 关键点分析 - **性能考量**: 对于大规模查询请求而言,频繁读取数据库可能带来额外负担因此建议预先加载常用词典项至内存缓存之中以便快速检索。 - **异常处理**: 如果遇到未知条目则应设定默认行为比如保留原始数或是抛出错误提示给开发者知晓问题所在位置便于后续修正完善程序逻辑结构更加健壮可靠[^1]. --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值