在Java开发中,注解常用于标记代码元素并附加配置信息,但注解的属性仅支持基本类型、字符串、枚举等有限类型,无法直接存储复杂对象。通过集成类型转换器(Converter),可以在运行时将注解中配置的字符串等基础类型参数转换为目标业务类型,提升注解的灵活性和实用性。

基础注解定义
首先我们需要定义一个自定义注解,在注解中声明需要转换的配置参数,这里以配置时间格式并转换为DateTimeFormatter对象为例:
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface DateFormat {
// 时间格式字符串,后续会通过转换器转为DateTimeFormatter
String value() default "yyyy-MM-dd HH:mm:ss";
}
编写类型转换器接口与实现
先定义通用的转换器接口,再实现针对DateFormat注解的转换器:
import java.time.format.DateTimeFormatter;
/**
* 通用类型转换器接口
* @param <S> 源类型
* @param <T> 目标类型
*/
public interface Converter<S, T> {
T convert(S source);
}
/**
* DateFormat注解对应的转换器,将字符串格式转为DateTimeFormatter
*/
public class DateFormatConverter implements Converter<String, DateTimeFormatter> {
@Override
public DateTimeFormatter convert(String source) {
if (source == null || source.trim().isEmpty()) {
return DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
}
return DateTimeFormatter.ofPattern(source);
}
}
运行时注解解析与转换器调用
在运行时通过反射获取注解信息,调用对应的转换器完成类型转换,以下是字段注解的处理示例:
import java.lang.reflect.Field;
import java.time.format.DateTimeFormatter;
public class AnnotationConverterDemo {
@DateFormat("yyyy/MM/dd")
private String customDate;
public static void main(String[] args) throws Exception {
// 获取当前类的指定字段
Field field = AnnotationConverterDemo.class.getDeclaredField("customDate");
// 判断字段是否标记了DateFormat注解
if (field.isAnnotationPresent(DateFormat.class)) {
DateFormat annotation = field.getAnnotation(DateFormat.class);
// 获取注解中配置的字符串值
String formatStr = annotation.value();
// 创建转换器实例并执行转换
Converter<String, DateTimeFormatter> converter = new DateFormatConverter();
DateTimeFormatter formatter = converter.convert(formatStr);
// 输出转换结果验证
System.out.println("转换后的DateTimeFormatter模式:" + formatter.toString());
}
}
}
多转换器统一管理
当项目中存在多个注解需要集成不同类型的转换器时,可以建立转换器注册中心统一管理:
import java.util.HashMap;
import java.util.Map;
public class ConverterRegistry {
private static final Map<Class<?>, Converter<?, ?>> CONVERTER_MAP = new HashMap<>();
static {
// 注册DateFormat注解对应的转换器
CONVERTER_MAP.put(DateFormat.class, new DateFormatConverter());
}
/**
* 根据注解类型获取对应的转换器
*/
@SuppressWarnings("unchecked")
public static <A, S, T> Converter<S, T> getConverter(Class<A> annotationClass) {
return (Converter<S, T>) CONVERTER_MAP.get(annotationClass);
}
}
修改之前的解析逻辑,通过注册中心获取转换器:
import java.lang.reflect.Field;
import java.time.format.DateTimeFormatter;
public class UnifiedConverterDemo {
@DateFormat("yyyy-MM-dd")
private String testDate;
public static void main(String[] args) throws Exception {
Field field = UnifiedConverterDemo.class.getDeclaredField("testDate");
if (field.isAnnotationPresent(DateFormat.class)) {
DateFormat annotation = field.getAnnotation(DateFormat.class);
// 从注册中心获取对应转换器
Converter<String, DateTimeFormatter> converter = ConverterRegistry.getConverter(DateFormat.class);
if (converter != null) {
DateTimeFormatter formatter = converter.convert(annotation.value());
System.out.println("统一管理的转换器转换结果:" + formatter.toString());
}
}
}
}
注意事项
- 注解的保留策略必须设置为
RetentionPolicy.RUNTIME,否则运行时无法通过反射获取注解信息。 - 转换器的实现需要考虑源参数为空或非法值的场景,避免运行时抛出异常。
- 如果转换逻辑较为复杂,可以在转换器中加入参数校验、异常提示等处理逻辑,提升代码的健壮性。