URLClassLoader loads Annotation as com.sun.$Proxy$27

牧云@^-^@ 提交于 2019-11-30 22:39:46
Andreas Panagiotidis

The fact that the reflection returns a proxy object does not prevent you from gathering information about the annotation and its values.

The getclass method returns a proxy object:

 log.info("annotation class:" + annotation.getClass());

Output:

 [INFO] annotation class:class com.sun.proxy.$Proxy16class 

The output is that same as in your example, but that is no problem. Having the method (or field) is enough. The additional part is to just invoke the annotation method.

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()) {
         //...
    }

}  

To come to this solution, I used the following post: How to get annotation class name, attribute values using reflection

The fact that you get a proxy in front of your annotation type should not matter. It might actually mislead you into believing that this is the cause for problems you are having. If stuff like "isAnnotationPresent(..)" fails, it is not due to that proxy, it is because you have loaded the annotation class multiple times using multiple classloaders. For example, Jetty gives priority to the WebApp classloader by default. So if your Jetty server instance (or Tomcat or whatever) already has loaded the annotation class, and the annotation is on your WebApp's classpath, too, you can have problems like "getAnnotation()" not returning anything. Just make sure that the library containing your annotation is not loaded twice.

The solution provided by Andreas is, well, a very dirty workaround and just covers up the fact that you probably don't have your classloading under control/properly organized.

I had the same problem when trying to create a ant task for code generation based on a declarative approach using annotations. I found that the documentation of the Proxy - Object states that instanceof should resolve it, but this didn't work fopr me neither. I finally got a around with

Annotation[] annotations = classObj.getAnnotations();

    for(int i = 0;i < annotations.length;i++) {
        Class<?>[] interfaces = annotations[i].getClass().getInterfaces();

        for(int i2 = 0; i2 < interfaces.length;i2++) {
            System.out.println("interface:" + interfaces[i2].getName());
        }

giving my the name of the original annotation, so comparing this name to the annotations classname will give you the desired result.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!