【上】java获取requestMapping上所有注解功能实现及取匿名注释类的值及 class com.sun.proxy.$Proxy140 转换出错

2 篇文章 0 订阅
2 篇文章 0 订阅

java获取requestMapping上所有注解功能实现及取匿名注释类的值及 class com.sun.proxy.$Proxy140 转换出错

1,多人相当然以为类似对象一样直接强转下就可以,结果迎来的是class com.sun.proxy.$Proxy140转换出错【想法很勇敢,现实很骨感】
//Class<A> operatorMappingAnnotationType
// 错误示例
OperatorMapping operatorMapping = (OperatorMapping)method.getMethodAnnotation(operatorMappingAnnotationType);

实质上会抛出 不能转换代理相关报错的,所以还是另辟蹊径吧,少年。

2,业务场景:

在开发过程中需要写一个插件或者小功能,需要根据不同的匿名的注释类来获取该注释下的相关内容,如:获取controller上的某注解的内容(该注解可能A项目是 @***A, B项目可能是@***B。。。。)或者直接传入类地址, 那么在具体实现的插件下面是完全不知道这个注解到底是哪个,但是又要在插件中去把 注解里面的内容给拿出来给调用方使用

3,在Java中,如果你需要访问动态代理类(如com.sun.proxy.$Proxy140)中的属性和值,你通常不能直接这么做,因为这些类是由Java运行时动态生成的,它们的属性和方法是私有的,不应该直接访问。

然而,如果你需要获取这些代理对象的一些信息,你可以使用反射来间接地获取。这里有一个例子,展示了如何使用反射来访问代理对象的一些信息:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Field;
 
public class ProxyInspector {
    public static void main(String[] args) throws Exception {
        // 假设你有一个代理对象的实例,名为proxy
        Object proxy = ...; // 这里应该是你的$Proxy140实例
 
        // 获取代理的InvocationHandler
        InvocationHandler handler = Proxy.getInvocationHandler(proxy);
 
        // 通过反射获取InvocationHandler的字段
        Field hField = handler.getClass().getDeclaredField("h");
        hField.setAccessible(true); // 设置为可访问
 
        // 获取代理的实际对象
        Object proxyTarget = hField.get(handler);
 
        // 现在你可以对proxyTarget做你想做的任何反射操作
        // 例如,获取它的属性值
        Field someField = proxyTarget.getClass().getDeclaredField("someFieldName");
        someField.setAccessible(true);
        Object fieldValue = someField.get(proxyTarget);
 
        System.out.println("Field value: " + fieldValue);
    }               
}

请注意,这种方法依赖于com.sun.proxy.$Proxy类的内部实现,它可能会在不同版本的JDK中发生变化,因此可能不是一个可移植或可靠的解决方案。此外,访问私有字段也违反了封装的原则,应当谨慎使用。

如果你需要这样的功能,通常意味着你的设计可能有改进的空间。例如,你可以考虑将必要的信息直接暴露给代理对象,或者使用一个不会造成这种情况的设计模式。

4,实际业务实例如下:
/**
     * 获取代理的InvocationHandler 具体得  实际对象内容
     * @version 2024-9-217:36:26
     * @author zj
     * @param <A>
     * @param method
     * @param operatorMappingAnnotationType
     * @param invocationHandlerField 获取代理的得指定字段属性名
     * @return
     */
    @SuppressWarnings("unchecked")
    public <A extends Annotation> Map<String, Object> getInvocationHandlerData(HandlerMethod method, Class<A> operatorMappingAnnotationType, String invocationHandlerField) {
        Map<String, Object> proxyTarget = new HashMap<String, Object>();
        try {
            String operatorMappingSrc = menuConfigProperties.getOperatorMappingSrc();
            Object proxy = null;
            if (operatorMappingAnnotationType != null) {
                proxy = method.getMethodAnnotation(operatorMappingAnnotationType);
            } else {
                // 获取对应类的class
                Class<A> operatorMappingNameClass = (Class<A>) Class.forName(operatorMappingSrc);
                proxy =  method.getMethodAnnotation(operatorMappingNameClass);
            }
            if (proxy == null) {
                return proxyTarget;
            }
            // 获取代理的InvocationHandler
            InvocationHandler handler = Proxy.getInvocationHandler(proxy);
            Class<? extends InvocationHandler> handlerClass = handler.getClass();
            // 指定的Annotation 的  memberValues 获取值  
            Field declaredField = handlerClass.getDeclaredField(invocationHandlerField);
            declaredField.setAccessible(true);
            // 获取代理的实际对象
            proxyTarget = (Map<String, Object>)declaredField.get(handler);
            log.info("getInvocationHandlerData proxyTarget = {}", proxyTarget);
            
            // 方式2 
//            A operatorMappingMethodAnnotation =  method.getMethodAnnotation(operatorMappingAnnotationType);
//            Class<? extends Annotation> annotationType = operatorMappingMethodAnnotation.annotationType();
//            Method[] declaredMethods = annotationType.getDeclaredMethods();
//            for (Method methodItem : declaredMethods) {
//                Object value = handler.invoke(proxy, methodItem, null);
//                String name = methodItem.getName();
//                log.info("name={}, value = {}", name, value);
//            }
        } catch (Exception e1) {
            log.error("getInvocationHandlerData {}", e1);
        }
        return proxyTarget;
    }

5,完整实现代码可看下篇:

进微信交流群可联系V:q1227260341,备注加java群

。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值