Java URLClassLoader将注释加载为com.sun.$Proxy$27
我正在尝试动态加载一个java类。基本思想是,jar包含在运行时动态加载的模块。我就是这样做的(我知道这很有技巧,但是没有其他方法可以动态地将jar添加到已经存在的类加载器afaik中): 每个模块都使用@module注释进行注释。因此,为了获得关于模块的更多信息,我尝试获取注释。问题是foo上的注释的类型是com.sun.$Proxy$27,而不是com.coderunner.Module,因此我得到了一个Java URLClassLoader将注释加载为com.sun.$Proxy$27,java,spring,annotations,classloader,urlclassloader,Java,Spring,Annotations,Classloader,Urlclassloader,我正在尝试动态加载一个java类。基本思想是,jar包含在运行时动态加载的模块。我就是这样做的(我知道这很有技巧,但是没有其他方法可以动态地将jar添加到已经存在的类加载器afaik中): 每个模块都使用@module注释进行注释。因此,为了获得关于模块的更多信息,我尝试获取注释。问题是foo上的注释的类型是com.sun.$Proxy$27,而不是com.coderunner.Module,因此我得到了一个 ClassCastException: Cannot cast com.sun.pro
ClassCastException: Cannot cast com.sun.proxy.$Proxy42 (id=64) to com.coderunner.Module
我得说我对这里发生的事情有点困惑。我想做的事可能吗?怎么做
编辑:我可能还应该提到,我正在spring/spring mvc和tomcat环境中尝试这一点。我在尝试基于使用注释的声明性方法创建代码生成的ant任务时遇到了相同的问题。 我发现代理对象的文档说明instanceof应该解决它, 但这对我也不起作用。 我终于找到了一个好朋友
Annotation[]annotations=classObj.getAnnotations()
for(int i=0;i
为my指定原始注释的名称,因此将此名称与注释类名进行比较将得到所需的结果。反射返回代理对象的事实并不妨碍您收集有关注释及其值的信息 getclass方法返回一个代理对象:
log.info("annotation class:" + annotation.getClass());
输出:
[INFO] annotation class:class com.sun.proxy.$Proxy16class
输出与示例中的相同,但这没有问题。具有方法(或字段)就足够了。附加部分是调用注释方法
public void analyseClass(Class myClass) {
for (Method method: myClass.getMethods()) {
System.out.println("aanotations :" + Arrays.toString(field.getAnnotations()));
for (Annotation annotation : method.getAnnotations()) {
log.info("annotation class:" + annotation.getClass());
log.info("annotation class type:" + annotation.annotationType());
Class<Annotation> type = (Class<Annotation>) annotation.annotationType();
/* extract info only for a certain annotation */
if(type.getName().equals(MyAnnotation.class.getName())) {
String annotationValue =
(String) type.getMethod("MY_ANNOTATION_CERTAIN_METHOD_NAME").invoke(annotation);
log.info("annotationValue :" + annotationValue);
break;
}
}
}
//do the same for the fields of the class
for (Field field : myClass.getFields()) {
//...
}
}
public void分析类(类myClass){
对于(方法:myClass.getMethods()){
System.out.println(“aanotations:+Arrays.toString(field.getAnnotations()));
for(注释:方法.getAnnotations()){
log.info(“注释类:+annotation.getClass());
log.info(“注释类类型:”+annotation.annotationType());
类在注释类型前面有一个代理这一事实应该无关紧要。它实际上可能会误导您,使您相信这是您遇到问题的原因。如果像“isAnnotationPresent(…)”这样的内容失败,这不是由于该代理,而是因为您使用多个类加载器多次加载注释类。例如,Jetty默认优先于WebApp类加载器。因此,如果您的Jetty服务器实例(或Tomcat或其他)已加载批注类,并且批注也位于您的WebApp的类路径上,您可能会遇到诸如“getAnnotation()”不返回任何内容之类的问题。只需确保包含批注的库未加载两次
Andreas提供的解决方案是一个非常肮脏的解决方法,只是掩盖了一个事实,即您可能无法控制/正确组织类加载
[INFO] annotation class:class com.sun.proxy.$Proxy16class
public void analyseClass(Class myClass) {
for (Method method: myClass.getMethods()) {
System.out.println("aanotations :" + Arrays.toString(field.getAnnotations()));
for (Annotation annotation : method.getAnnotations()) {
log.info("annotation class:" + annotation.getClass());
log.info("annotation class type:" + annotation.annotationType());
Class<Annotation> type = (Class<Annotation>) annotation.annotationType();
/* extract info only for a certain annotation */
if(type.getName().equals(MyAnnotation.class.getName())) {
String annotationValue =
(String) type.getMethod("MY_ANNOTATION_CERTAIN_METHOD_NAME").invoke(annotation);
log.info("annotationValue :" + annotationValue);
break;
}
}
}
//do the same for the fields of the class
for (Field field : myClass.getFields()) {
//...
}
}