15

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

 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)

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

4

3 回答 3

12

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

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

尝试:

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

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

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

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

于 2012-11-14T13:31:15.807 回答
6

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

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

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

于 2008-10-17T06:31:00.780 回答
0

我在使用 spring boot 时遇到了同样的问题,我通过注入 ResourceLoader 来解决它,获取它的类加载器。

@Autowired
private ResourceLoader resourceLoader;

....
ClassLoader classLoader = resourceLoader.getClassLoader();
...


Proxy.newProxyInstance(
  classLoader, //for example...
  new Class < ? >[] {MyInterface.class},
  new InvocationHandler() {
  // (...)
});
于 2020-11-25T12:11:07.937 回答