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:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM