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

前端 未结 3 1870
小鲜肉
小鲜肉 2021-01-06 08:27

I\'m trying to dynamically load a java class. The basic idea is, that a jar contains modules which get loaded dynamically at runtime. This is how I do it (I know it\'s hacky

相关标签:
3条回答
  • 2021-01-06 08:46

    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.

    0 讨论(0)
  • 2021-01-06 09:08

    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

    0 讨论(0)
  • 2021-01-06 09:08

    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.

    0 讨论(0)
提交回复
热议问题