Can't get annotations from classes loaded by custom classloader in tomcat

 ̄綄美尐妖づ 提交于 2020-01-03 17:25:08

问题


Given the class org.popper.example.pages.Login

@Page(name="Login")
public interface Login {
}

exported to c:\pos\example.jar and the following servlet

public class PopperServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public static void main(String[] args) throws MalformedURLException, ClassNotFoundException {
        URLClassLoader ucl = new URLClassLoader(new URL[] {new File("c:/pos/example.jar").toURI().toURL()});
        System.out.println(Arrays.asList(ucl.loadClass("org.popper.example.pages.Login").getAnnotations()));
    }

    public PopperServlet() throws MalformedURLException, ClassNotFoundException {
        URLClassLoader ucl = new URLClassLoader(new URL[] {new File("c:/pos/example.jar").toURI().toURL()});
        System.out.println(Arrays.asList(ucl.loadClass("org.popper.example.pages.Login").getAnnotations()));
   }
}

Running the code as main shows the expected result

[@org.popper.fw.annotations.Page(name=Login)]

Running the code as servlet in tomcat doesn't find the annotations

[]

Can anybody tell me why?


回答1:


It's the same as always: Regard the classloader-hierarchy!

new URLClassLoader(new URL[] {new File("c:/pos/example.jar").toURI().toURL()}, PopperServlet.class.getClassloader());

did the trick. But it's surprising that annotations aren't found instead a ClassNotFoundException or NoClassDefError, thats what I expected when annotations are not found when loading a class...




回答2:


Yea sure you'll not find your annotation, you have to annotate your annotation to keep alive for the run time, add :

@Retention(RetentionPolicy.RUNTIME)

Retention Java doc : Indicates how long annotations with the annotated type are to be retained. If no Retention annotation is present on an annotation type declaration, the retention policy defaults to RetentionPolicy.CLASS.

for more details : here




回答3:


I have encountered the same problem. And I resolve it by my custome class loader as followed, Maybe you can have a try.

ClassLoader Code:

import java.util.HashMap;
import java.util.Map;
/**
 * Load class from byte[] which is compiled in memory.
 *
 * @author David
 */
class CustomClassLoader extends ClassLoader {

    // class name to class bytes:
    private Map<String, byte[]> classBytes = new HashMap<String, byte[]>();

    public CustomClassLoader(Map<String, byte[]> classBytes) {
        super(CustomClassLoader.class.getClassLoader());
        Thread.currentThread().setContextClassLoader(this);
        this.classBytes.putAll(classBytes);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] buf = classBytes.get(name);
        if (buf == null) {
            return super.findClass(name);
        }
        classBytes.remove(name);
        return defineClass(name, buf, 0, buf.length);
    }

}

Client Code:

byte[] code = this.createEntity(logicalTable, keyCount, relationMap);
Map<String, byte[]> results = Maps.newHashMap();
results.put(this.entityPackage + "." + logicalTable.getTableName(), code);
CustomClassLoader classLoader = new CustomClassLoader(results);
Class<?> clazz = classLoader.findClass(this.entityPackage + "." + logicalTable.getTableName());


来源:https://stackoverflow.com/questions/20451498/cant-get-annotations-from-classes-loaded-by-custom-classloader-in-tomcat

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