• JDK动态代理+反射实现动态修改注解属性值


      这是最近朋友的一个需求,正好闲来无聊有些时间,跟着研究一下,如有不正确的地方,欢迎大家指正~

    一、准备自定义注解

      注:如何实现自定义注解,请移步百度。

     二、实现

    1、实现方式1:通过反射+动态代理动态修改自定义注解的属性

    public class ModifyAnnotaionFactory {
        private static ModifyAnnotaionFactory instance = null;
        public static ModifyAnnotaionFactory newInstance()
        {
    
            if (instance == null)
            {
                synchronized (ModifyAnnotaionFactory.class)
                {
                    if (instance == null)
                    {
                        instance = new ModifyAnnotaionFactory();
                    }
                }
            }
    
            return instance;
        }
        private ModifyAnnotaionFactory(){}
    
        /**
         *
         * @param className         当前类名.class
         * @param annotationName    需要修改的注解class
         * @param methodName        需要修改的方法名
         * @param modifyField       注解中需要修改的属性名
         * @param paramName         注解中修改的属性值
         * @param paramTypes        不定参数----语法糖
         */
        public Annotation ModifyAnnotation(Class className,Class annotationName,
                                        String methodName,String modifyField,String paramName,Class<?>... paramTypes)
        {
            try
            {
                //反射获取Method:methodName方法、paramTypes不定参数(“语法糖”)-----method
                Method method = className.getDeclaredMethod(methodName,paramTypes);
                //反射当前方法的注解---annotation
                Annotation annotation = method.getAnnotation(annotationName);
                //获取该注解的调用处理器---invocationHandler
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
                //反射获取注解的属性
                Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
                //暴力破解
                memberValues.setAccessible(true);
                //获取所有的注解属性--map集合
                Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
                //覆盖原有属性值
                values.put(modifyField, paramName);
                return annotation;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    
        /**
         *
         * @param classAllPath      当前类的全路径名
         * @param annotationName    需要修改的注解class
         * @param methodName        需要修改的方法名
         * @param modifyField       注解中需要修改的属性名
         * @param paramName         注解中修改的属性值
         * @return
         */
        public boolean ModifyAnnotation(String classAllPath,Class annotationName,String methodName,String modifyField,String paramName)
        {
            try
            {
                Class<?> aClass = Class.forName(classAllPath);
                Method method = aClass.getDeclaredMethod(methodName);
                Annotation annotation = method.getAnnotation(annotationName);
                InvocationHandler invocationHandler = Proxy.getInvocationHandler(annotation);
                Field memberValues = invocationHandler.getClass().getDeclaredField("memberValues");
                memberValues.setAccessible(true);
                Map<String, Object> values = (Map<String, Object>) memberValues.get(invocationHandler);
    
                Object o1 = values.get(modifyField);
                values.put(modifyField, paramName);
                Object o2 = values.get(modifyField);
                System.out.println();
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    
        /**
         * 获取当前注解
         * @param className         当前类名
         * @param annotationName    注解名
         * @param name              方法名、类名、属性名之一
         * @param type              注解类型
         * @return
         * @throws Exception
         */
        public Annotation getAnnotation(Class className,Class annotationName,String name,Integer type) throws Exception {
            switch (type){
                case 1:
                    Method method = className.getDeclaredMethod(name);
                    return method.getAnnotation(annotationName);
                case 2:
                    System.out.println("2");
                    return null;
                case 3:
                    System.out.println("3");
                    return null;
            }
            return null;
        }
    工具类

    测试结果如下:

    2、实现方式2:

  • 相关阅读:
    pdf在线转换器
    抖音修复老照片动起来笑起来的程序app的下载地址
    FFmpeg.AutoGen Unable to load DLL 'avutil.56' 解决方法
    Array.prototype.fill 填充值被复用的问题
    Recoil Input 光标位置被重置到末尾的问题
    TypeScript 扩展全局 Window 时报错的解决
    Recoil 中默认值的正确处理
    Recoil 中多级数据联动及数据重置的合理做法
    Recoil 默认值及数据级联的使用
    Recoil 的使用
  • 原文地址:https://www.cnblogs.com/rmxd/p/11823933.html
Copyright © 2020-2023  润新知