Java 8升级Java 17的反射修改static final属性方法

2023-12-19 22:46:27

最近在处理用动态修改Retrofit代理Server类的注释过程,想通过反射动态修改@GET/@POST注释后路径地址,
发现在java 8中可以修改,由于项目使用17,提示不可用。
参考文章:https://blog.csdn.net/wu_weijie/article/details/129251045

报错:java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.Map
Exception in thread “main” java.lang.reflect.InaccessibleObjectException: Unable to make field private final java.util.Map sun.reflect.annotation.AnnotationInvocationHandler.memberValues accessible: module java.base does not “opens sun.reflect.annotation” to unnamed module @6325a3ee

解决方法:
在运行VM options值
–add-opens java.base/sun.reflect.annotation=ALL-UNNAMED
关于–add-opens介绍文章:https://blog.51cto.com/u_16175510/6686606

代码样例:
TestController类

public class TestController {

    public static void main(String[] args) throws Exception {
        TestController retrofitTestController = new TestController();
        retrofitTestController.changeBaseUrl();
    }

    @SneakyThrows
    public static <T extends Annotation> void setValueToAnnotate(T annotation, String valueName, Object value) {
        InvocationHandler invocationHandler = null;
        if (Objects.nonNull(annotation)) {
            invocationHandler = Proxy.getInvocationHandler(annotation);
        }
        if (Objects.isNull(invocationHandler)) {
            return;
        }
        /**
         *class AnnotationInvocationHandler implements InvocationHandler, Serializable {
         *     @java.io.Serial
         *     private static final long serialVersionUID = 6182022883658399397L;
         *     private final Class<? extends Annotation> type;
         *     @SuppressWarnings("serial") // Not statically typed as Serializable
         *     private final Map<String, Object> memberValues;
         */
        Field nameField = invocationHandler.getClass().getDeclaredField("memberValues");
        nameField.setAccessible(true);
        Map<String, Object> memberValues = (Map<String, Object>) nameField.get(invocationHandler);
        memberValues.put(valueName, value);
    }


    public void changeBaseUrl() throws Exception {
        //获取对方指定方法
        Method sMethod =  GitHubService.class.getDeclaredMethod("listRepos", String.class);
        System.out.println("方法名:"+sMethod.getName());
        if (sMethod.isAnnotationPresent(GET.class)) {
            GET annotation = sMethod.getAnnotation(GET.class);
            System.out.println("注释内容:"+annotation.value());
            TestController.setValueToAnnotate(annotation, "value", "users/v2/{user}/repos");
            System.out.println("修改后注释内容:"+annotation.value());
        }else{
            System.out.println("不存在GET注释。。");
        }
    }
}

GitHubService.java

public interface GitHubService {

    @GET("users/{user}/repos")
    Call<List<Object>> listRepos(@FieldMap @Path("user") String user);
}

文章来源:https://blog.csdn.net/xianglingchuan/article/details/135094433
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。