java 自定义注解实现不同对象之间的拷贝(支持大小写、驼峰转换)

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)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现不同目标方法执行不同逻辑,可以使用Java自定义注解反射机制。 首先,自定义注解需要用@Target注解来指定使用范围,例如可以指定在方法上使用,即@Target(ElementType.METHOD)。 其次,注解需要用@Retention注解来指定生命周期,例如可以指定在运行时依然存在,即@Retention(RetentionPolicy.RUNTIME)。 然后,在目标方法上加上自定义注解,并通过反射获取注解信息,根据注解信息执行不同逻辑。 下面是一个简单的示例代码: ``` @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String value(); } public class AnnotationDemo { @MyAnnotation("method1") public void method1() { System.out.println("This is method1"); } @MyAnnotation("method2") public void method2() { System.out.println("This is method2"); } public static void main(String[] args) throws Exception { AnnotationDemo demo = new AnnotationDemo(); Method[] methods = demo.getClass().getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(MyAnnotation.class)) { MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); if (annotation.value().equals("method1")) { method.invoke(demo); } else if (annotation.value().equals("method2")) { method.invoke(demo); } } } } } ``` 在上面的示例代码中,定义了一个自定义注解@MyAnnotation,并在AnnotationDemo类中的两个方法上分别加上了该注解,并指定了不同的value值。 在main方法中,通过反射获取AnnotationDemo类中的所有方法,判断方法上是否加上了@MyAnnotation注解,如果有,则获取注解信息,并根据注解信息执行不同的逻辑。 在这个简单的例子中,我们可以看到使用自定义注解反射机制可以实现不同目标方法执行不同逻辑的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值