java 自定义注解实现不同对象之间的拷贝(支持大小写、驼峰转换)
1、需求
要实现两个属性名称完全不同的对象之间的拷贝。具体如下
-
原对象
/** * 原实体 */ @Data public class Source { /** * 按属性名称转 */ @PropertyTransform(name = "targetName",transformStrategy = TransformStrategy.DEFAULT) String sourceName; /** * 大写转小写 */ @PropertyTransform(transformStrategy = TransformStrategy.LOWER) String LOWER; /** * 小写转大写 */ @PropertyTransform(transformStrategy = TransformStrategy.UPPER) String upper; /** * 驼峰命名 */ @PropertyTransform(transformStrategy = TransformStrategy.HUMP) String high_and_down; }
-
目标对象
/**
* 目标实体
*/
@Data
public class Target {
String targetName;
String lower;
String UPPER;
String highAndDown;
}
2、实现
我们可以看到上面原对象上的属性加入了自定义注解==@PropertyTransform==,具体实现如下
- 自定义注解
//RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Retention(RetentionPolicy.RUNTIME)
//声明注解的作用域在属性上
@Target(ElementType.FIELD)
@Component
public @interface PropertyTransform {
/**
* 目标属性
* @return
*/
@AliasFor("name")
String value() default "";
/**
* 目标属性
* @return
*/
@AliasFor("value")
String name() default "";
/**
* 转换策略 见枚举类
* @return
*/
TransformStrategy transformStrategy() default TransformStrategy.DEFAULT;
}
-
转换策略枚举类
/** * 转换策略 */ public enum TransformStrategy { /** * 按名称转 */ DEFAULT, /** * 小写 */ LOWER, /** * 大写 */ UPPER, /** * 驼峰 */ HUMP, }
-
编写转换工具类,利用反射实现需求
public class PropertiesTransformUtils {
private static final Pattern linePattern = Pattern.compile("_(\\w)");
@SneakyThrows
public static Object copy(Object source,Class<?> target){
Class<?> sourceClass = source.getClass();
//获取原实体下的所有属性
Field[] fields = sourceClass.getDeclaredFields();
//记录转换名称后的属性名以及属性值
Map<String,Object> objMap = new HashMap<>(fields.length);
for (Field field : fields) {
field.setAccessible(true);
//获取属性上的注解
PropertyTransform propertyTransform = field.getAnnotation(PropertyTransform.class);
//根据不同的策略进行对原实体的属性名称进行修改
if (propertyTransform != null){
if (!"".equals(propertyTransform.name())){
objMap.put(propertyTransform.name(),field.get(source));
}else if (!TransformStrategy.DEFAULT.equals(propertyTransform.transformStrategy())){
if (TransformStrategy.LOWER.equals(propertyTransform.transformStrategy())){
objMap.put(field.getName().toLowerCase(),field.get(source));
}else
if (TransformStrategy.UPPER.equals(propertyTransform.transformStrategy())){
objMap.put(field.getName().toUpperCase(),field.get(source));
}else
if (TransformStrategy.HUMP.equals(propertyTransform.transformStrategy())){
objMap.put(lineToHump(field.getName()),field.get(source));
}
}
}
}
//将值拷贝到目标实体
Object targetObj = target.newInstance();
for (Field declaredField : target.getDeclaredFields()) {
Object value = objMap.getOrDefault(declaredField.getName(),null);
declaredField.setAccessible(true);
declaredField.set(targetObj,value);
}
return targetObj;
}
/** 下划线转驼峰 */
public static String lineToHump(String str) {
str = str.toLowerCase();
Matcher matcher = linePattern.matcher(str);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
}
matcher.appendTail(sb);
return sb.toString();
}
}
3、测试
@Test
public void testPT(){
Source source = new Source();
source.setUpper("upper");
source.setHigh_and_down("highanddown");
source.setLOWER("lower");
source.setSourceName("sourceName");
System.out.println(source.toString());
Target target = (Target) PropertiesTransformUtils.copy(source,Target.class);
System.out.println(target.toString());
}
测试结果
Source(sourceName=sourceName, LOWER=lower, upper=upper, high_and_down=highanddown)
Target(targetName=sourceName, lower=lower, UPPER=upper, highAndDown=highanddown)