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群
。。。。。