精华内容
下载资源
问答
  • Java动态修改注解的属性

    千次阅读 2019-06-13 19:10:01
    以往来看,注解的属性一般都是“硬编码”。但最近在开发过程中遇到了需要根据运行环境来设置Retention 为 RUNTIME (运行期保留)的注解属性的需求。举个例子: @Table(name="t1") public class Test { private...

    前言

    以往来看,注解的属性值一般都是“硬编码”。但最近在开发过程中遇到了需要根据运行环境来设置 Retention 为 RUNTIME (运行期保留) 的注解属性值的需求。举个例子:

    @Table(name="t1")
    public class Test {
      private String id;
     ...
    }

    对于上述类 Test,其上有一个注解 @Table,需求是这样的: 在测试环境 name 值为"t1",在其他环境 name 值为"t2"

    实现方法

    知识点:

    • 保留策略为 RUNTIME 的注解在运行期是保留的。
    • 出于某些技术原因,Java 虚拟机使用的“真实”注释类的实例是动态代理的实例。
    • Java 注解有一个名为 memberValues 的私有Map,其中存储了属性名称和属性值的k-v对。

    基于上述知识点,可以通过反射来访问实例,然后用给定的新值替换现有值。

    相关的类:

    • Proxy JDK 动态代理大佬
      可通过其 getInvocationHandler 方法获取注解的代理实例
    • InvocationHandler 调用处理器,每一个被代理的实例都有一个调用处理器
      通过反射获取被代理类的实例的属性值

    示例代码:

    // 根据运行环境获取表名
    String tableName = getTable();
    // 获取 Test 上的注解
    Table annoTable = Test.class.getAnnotation(Table.class);
     
    if (annoTable == null) {
      throw new RuntimeException("please add @Table for Test");
    }
    // 获取代理处理器
    InvocationHandler invocationHandler = Proxy.getInvocationHandler(annoTable);
    // 获取私有 memberValues 属性
    Field f = invocationHandler.getClass().getDeclaredField("memberValues");
    f.setAccessible(true);
    // 获取实例的属性map
    Map<String, Object> memberValues = (Map<String, Object>) f.get(invocationHandler);
    // 修改属性值
    memberValues.put("name", tableName);

     

    补充(获取方法的注解的值):

        public void getAnnotationValues(Object obj){
            //解析方法上的注解
            Method[] methods = obj.getClass().getDeclaredMethods();
            for(Method method : methods){
                //是否使用MyAnno注解
                boolean methodHasAnno = method.isAnnotationPresent(MockSwitch.class);
                if(methodHasAnno){
                    //得到注解
                    MockSwitch methodAnno = method.getAnnotation(MockSwitch.class);
                    //输出注解属性
                    boolean status = methodAnno.status();
                    String mockResult = methodAnno.mockResult();
                    System.out.println(method.getName());
                }
            }
        }

     

    转载自:https://blog.csdn.net/weixin_34242509/article/details/88178897

    展开全文
  • Java 使用动态代理来动态修改注解值

    万次阅读 2017-11-02 09:32:17
    java 中定义注解都是在编写代码时,如果我们想在运行中根据某个条件来修改注解。是无法注解操作的,但是通过动态代理是可以实现的。这里需要用到的是Proxy 动态代理第一步得到代理实例:InvocationHandler ...

    java 中定义注解都是在编写代码时,如果我们想在运行中根据某个条件来修改注解的值。是无法注解操作的,但是通过动态代理是可以实现的。这里需要用到的是Proxy 动态代理

    第一步得到代理实例:

    InvocationHandler invocationHandler = Proxy.getInvocationHandler(componentScan);

    然后再通过代理示例来操作注解上的值:
    InvocationHandler 是个接口,每个代理实例类都会实现这个接口,如果需要代理其他类型的先调试下代理实例的实现类,方便操作对应的属性和方法。这里举例说明的是注解的代理实例

    sun.reflect.annotation.AnnotationInvocationHandler

    第二步获取代理实例中的属性:

    Field value = invocationHandler.getClass().getDeclaredField("memberValues");
    value.setAccessible(true);
    Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);

    第三步回去对应注解值:

     String[] values = (String[]) memberValues.get("value");

    这里value 是注解中的属性名称 ,返回的则是属性对应类型

    第四步按需修改值:
    (我这里是想数组添加一个元素)

    String[] newValues = new String[values.length + 1];
    System.arraycopy(values, 0, newValues, 0, values.length);
    newValues[newValues.length - 1] = "cn.jiangzeyin";

    第五步将值保存到代理实例中:

    memberValues.put("value", newValues);

    完整实例:

    ComponentScan componentScan = (ComponentScan) tclass.getAnnotation(ComponentScan.class);
    InvocationHandler invocationHandler = Proxy.getInvocationHandler(componentScan);
    Field value = invocationHandler.getClass().getDeclaredField("memberValues");
    value.setAccessible(true);
    Map<String, Object> memberValues = (Map<String, Object>) value.get(invocationHandler);
    String[] values = (String[]) memberValues.get("value");
    String[] newValues = new String[values.length + 1];
    System.arraycopy(values, 0, newValues, 0, values.length);
    newValues[newValues.length - 1] = "cn.jiangzeyin";
    memberValues.put("value", newValues);
    展开全文
  • 以往来看,注解的属性一般都是“硬编码”。但最近在开发过程中遇到了需要根据运行环境来设置注解属性的需求。 举个例子: package com.das.common.util.csv; import java.lang.annotation.*; /** * @...

    以往来看,注解的属性值一般都是“硬编码”。但最近在开发过程中遇到了需要根据运行环境来设置注解属性值的需求。

    举个例子:

    package com.das.common.util.csv;
    
    import java.lang.annotation.*;
    
    /**
     * @Author liangmy
     * @Date 2018/10/15
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    public @interface Header {
        String value() default "";
        double priority() default Double.MAX_VALUE;
        String format() default "";
        HeaderGroupConfigure[] groups() default {};
    }
    
    package com.das.common.util.csv;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * @Author liangmy
     * @Date 2019/3/17
     */
    @Target(ElementType.ANNOTATION_TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface HeaderGroupConfigure {
        String headName() default "";
        String groupName();
        double priority() default Double.MAX_VALUE;
        String format() default "";
    }
    

    根据HeaderGroupConfigure是否配置priority,修改Header的priority。

     

    知识点:

    • 保留策略为 RUNTIME 的注解在运行期是保留的。
    • 出于某些技术原因,Java 虚拟机使用的“真实”注释类的实例是动态代理的实例。
    • Java 注解有一个名为 memberValues 的私有Map,其中存储了属性名称和属性值的k-v对。

    基于上述知识点,可以通过反射来访问实例,然后用给定的新值替换现有值。

    相关的类:

    • Proxy JDK 动态代理
      可通过其 getInvocationHandler 方法获取注解的代理实例
    • InvocationHandler 调用处理器,每一个被代理的实例都有一个调用处理器
      通过反射获取被代理类的实例的属性值

    示例代码:

            // 获取 Header 注解
            Header headerAnnotation = field.getDeclaredAnnotation(Header.class);
            if (null != headerAnnotation) {
                // 获取 Header 中 分组 HeaderGroupConfigure 注解
                HeaderGroupConfigure[] groups = headerAnnotation.groups();
                for (HeaderGroupConfigure group : groups) {
                    if (groupNameSet.contains(group.groupName())) {
                        // 计算最终的属性值
                        double groupPriority = Double.MAX_VALUE == group.priority() ? headerAnnotation.priority() : group.priority();
                        // 获取代理处理器
                        InvocationHandler invocationHandler = Proxy.getInvocationHandler(headerAnnotation);
                        // 获取私有 memberValues 属性
                        Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues");
                        memberValuesField.setAccessible(true);
                        // 获取实例的属性map
                        Map<String, Object> memberValuesValue = (Map<String, Object>) memberValuesField.get(invocationHandler);
                        // 修改属性值
                        memberValuesValue.put("priority", groupPriority);
                    }
                }
            }
    

    略略略

    展开全文
  • Java 反射动态获取和修改注解值Java 反射动态获取和修改注解值创建自定义注解:`TargetAnnotation.java`创建自定义注解:`Property.java`创建测试Bean:`Bean.java`测试测试结果 Java 反射动态获取和修改注解值 ...

    Java 反射动态获取和修改注解值

    目的:通过注解 TargetAnnotation 的配置,动态获取和修改注解 Property

    创建自定义注解:TargetAnnotation.java

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Documented
    @Target(ElementType.FIELD)
    @Retention(value = RetentionPolicy.RUNTIME)
    public @interface TargetAnnotation {
        /**
         * 目标注解类
         */
        Class<?> targetAnnotationClass() default Void.class;
    
        /**
         * 目标注解属性
         */
        String targetAnnotationClassField() default "";
    }
    

    创建自定义注解:Property.java

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Documented
    @Target(ElementType.FIELD)
    @Retention(value = RetentionPolicy.RUNTIME)
    public @interface Property {
    
        String name() default "";
    }
    

    创建测试Bean:Bean.java

    public class Bean {
        
        @Property(name = "名称")
        @TargetAnnotation(targetAnnotationClass = Property.class , targetAnnotationClassField = "name")
        private String name;
    }
    

    测试

    import java.lang.annotation.Annotation;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Proxy;
    import java.util.Map;
    
    public class Test {
    
        public static void main(String[] args) throws Exception {
            Field nameField = Bean.class.getDeclaredField("name");
    
            TargetAnnotation targetAnnotation = nameField.getAnnotation(TargetAnnotation.class);
    
            // 获取标注的目标注解类
            Class<? extends Annotation> targetAnnotationClass = (Class<? extends Annotation>) targetAnnotation.targetAnnotationClass();
    
            // 获取 TargetAnnotation.targetAnnotationClass 标注的注解代理实例
            Annotation annotation = nameField.getAnnotation(targetAnnotationClass);
    
            // 获取代理实例所持有的 InvocationHandler
            InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
    
            // 获取 AnnotationInvocationHandler 的 memberValues 字段
            Field memberValuesField = invocationHandler.getClass().getDeclaredField("memberValues");
    
            // 打开访问权限
            memberValuesField.setAccessible(true);
    
            // 获取 memberValues (目标注解的信息都在 memberValues 中)
            Map memberValues = (Map) memberValuesField.get(invocationHandler);
    
            // 1)、动态获取 TargetAnnotation.targetAnnotationClassField 标注的注解属性值
            Object targetAnnotationClassField = memberValues.get(targetAnnotation.targetAnnotationClassField());
            System.out.println("修改前:" + targetAnnotationClassField);
    
            // 2)、动态修改 TargetAnnotation.targetAnnotationClassField 标注的注解属性值
            memberValues.put(targetAnnotation.targetAnnotationClassField(), "用户名");
    
            // 3)、再次获取修改后的 TargetAnnotation.targetAnnotationClassField 标注的注解属性值
            targetAnnotationClassField = memberValues.get(targetAnnotation.targetAnnotationClassField());
            System.out.println("修改后:" + targetAnnotationClassField);
        }
    }
    

    测试结果

    修改前:名称
    修改后:用户名
    
    展开全文
  • Java反射动态修改注解

    千次阅读 2018-03-11 14:48:47
    先来看看通常情况下,我们通过反射获取注解的场景:那么现在我们定义一个 @Foo 注解,它有一个类型为 String 的 value 属性,该注解应用再Field上:/** * @Author 落叶飞翔的蜗牛 * @Date 2018/3/11 * @...
  • java动态修改注解的某个属性

    千次阅读 2020-09-15 19:57:08
    这个题目我并不是很熟悉,不过根据题目描述和查阅相关Spring 创建定时任务的资料,发现这也许涉及到通过Java代码动态修改注解的属性。 今天对此尝试了一番,发现通过反射来动态修改注解的属性是可以做到的: ...
  • JAVA使用变量动态修改注解属性

    千次阅读 2020-07-17 14:51:14
    JAVA使用变量动态修改注解属性问题场景反射基础动态修改注解属性的实现问题场景的修复 问题场景 在使用easyexcel做数据导出时,用到了注解@ExcelProperty标记表头,代码如下: import ...
  • Java 动态修改 实体类的注解值 实体类 @Data public class RsPersonalHolidayExcel { ...修改注解值 // 通过反射 获取目标实体类的目标字段 Field file= RsPersonalHolidayExcel.class.getDeclared
  • java 动态修改方法上的注解值

    万次阅读 热门讨论 2018-04-15 22:35:18
    上篇博客提起,动态修改类上注解的值。有博友问题如果修改方法上注解值,其实二者是相通的。 代码如下: import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import j...
  • Java 运行时动态修改注解的属性
  • Java修改注解属性

    千次阅读 2018-04-20 09:12:48
    // 修改 name,configuration 属性 memberValues.put("name", "client"); Class[] configuration2 = { TestConfigurationInsideScanPackage2.class }; memberValues.put("configuration", configuration2);...
  • //修改注解 System.out.println(extendParams1.toString()); System.out.println(JSON.toJSONString(a)); } } 去掉main里面的注解看看效果,这个好像是发生了jvm优化导致的问题。。。 注释第一个print 打印结果...
  • Java运行时反射修改注解值

    千次阅读 2018-11-12 16:11:30
    Java实现运行时修改注解值 由于java的注解不能传参,而项目中经常需要将运行中动态值传到注解中,因为需要在运行中修改注解的值,达到我们想要的目的。再次记录我项目中实现java通过反射实现运行时修改注解值。 ...
  • 这个题目我并不是很熟悉,不过根据题目描述和查阅相关Spring 创建定时任务的资料,发现这也许涉及到通过Java代码动态修改注解的属性。 今天对此尝试了一番,发现通过反射来动态修改注解的属性是可以做到的...
  • java 使用javassist 动态修改注解

    千次阅读 2017-02-23 19:29:56
    如下实例: @Test public void aetTestCaseAtrributes() throws NotFoundException { ClassPool pool = ClassPool.... // 获取需要修改的类 CtClass ct = pool.get("com.tmall.test.scv.testcases.SCVDRCSc
  • 主要介绍了java注解之运行时修改字段的注解值操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 废话不多说,相信点进这篇博客的看客需求肯定是需要动态的使用代码进行修改注解,可能看了很多博客,尝试了很多方法,都没有实现。那么恭喜你,马上就可以实现了,只要你耐心的花上一点点时间看我这篇博客即可。...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 118,816
精华内容 47,526
关键字:

java动态修改注解的值

java 订阅