Java 使用代理时,类加载器看不到接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/211176/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:25:33  来源:igfitidea点击:

Interface is not visible from ClassLoader when using a proxy?

javadynamicproxy

提问by

I am seeing following exception when I try to use dynamic proxy

当我尝试使用动态代理时,我看到以下异常

 com.intellij.rt.execution.application.AppMain DynamicProxy.DynamicProxy
Exception in thread "main" java.lang.IllegalArgumentException: interface Interfaces.IPerson is not visible from class loader
    at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
    at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
    at DynamicProxy.Creator.getProxy(Creator.java:18)
    at DynamicProxy.DynamicProxy.main(DynamicProxy.java:54)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Any idea what I need to do to resolve it

知道我需要做什么来解决它

回答by ddimitrov

When your DynamicProxytries to do Class.forName(youInterfaceClass.getName())the resulting java.lang.Classinstance is different from the one you passed when you created the proxy. In other words you have two class objects with the same name and the proxy is not sure which one is the right one (doesn't matter whether they are the same).

当您DynamicProxy尝试执行Class.forName(youInterfaceClass.getName())结果java.lang.Class实例与创建代理时传递的实例不同时。换句话说,您有两个同名的类对象,代理不确定哪一个是正确的(它们是否相同无关紧要)。

Usually, this happens when the interface you are trying to proxy is in a library loaded through two different classloaders (i.e. Tomcat's 'common' and 'application').

通常,当您尝试代理的接口位于通过两个不同的类加载器(即 Tomcat 的“common”和“application”)加载的库中时,就会发生这种情况。

If this doesn't help, please post more info on your application - especially if you are using any application server, Spring or OSGi.

如果这没有帮助,请发布有关您的应用程序的更多信息 - 特别是如果您使用任何应用程序服务器、Spring 或 OSGi。

回答by omnomnom

If this is web application, then you should use the web application classloader when creating dynamic proxy. So, for example instead of:

如果这是 Web 应用程序,那么您应该在创建动态代理时使用 Web 应用程序类加载器。因此,例如,而不是:

Proxy.newProxyInstance(
  ClassLoader.getSystemClassLoader(),
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
    // (...)
});

try:

尝试:

Proxy.newProxyInstance(
  this.getClass().getClassLoader(), // here is the trick
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
    // (...)
});

For instance, hierarchy of tomcat class loaders (other web containers have similar) is following:

例如,tomcat 类加载器的层次结构(其他 Web 容器也类似)如下:

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ... 

And it is the webapp classloader which contains classes and resources in the /WEB-INF/classes directory of your web application, plus classes and resources in JAR files under the /WEB-INF/lib directory of your web application.

它是 webapp 类加载器,它包含 Web 应用程序 /WEB-INF/classes 目录中的类和资源,以及 Web 应用程序 /WEB-INF/lib 目录下 JAR 文件中的类和资源。