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

2019/11/08 23:57
阅读数 347

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

一、准备自定义注解

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

 二、实现

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:

展开阅读全文
jdk
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部