【问题标题】:Java/JSF/Tomcat/Spring - Proxy-Object has different methods than original objectJava/JSF/Tomcat/Spring - Proxy-Object 具有与原始对象不同的方法
【发布时间】:2013-08-09 20:00:01
【问题描述】:

今天我遇到了这个问题,这真的让我很烦恼,因为几乎代码已经工作了(即使在恢复到旧版本后也停止工作)。

我正在访问 Facelets 页面上的 Spring-Bean。 Spring 将这些对象包装在代理中以使用方面和其他一些东西。

问题是,我在尝试访问 bean 的属性时遇到异常。例外是这样的:

javax.el.PropertyNotFoundException: /customers.xhtml @23,27 value="#{customerBean.customer}": Property 'customer' not found on type $Proxy88

我确定 (!!) 有相应的 getter/setter 方法。 到目前为止我尝试过的事情:

  • 将应用程序部署到另一个 tomcat 安装
  • 清除所有 tomcat 缓存,webapp 目录
  • 清理 eclipse 项目
  • 使用 javap 检查相应的方法(以及那里的方法/属性)
  • 更改 bean 的范围
  • 更改 bean 的类名
  • 更改 spring bean-id
  • 更改 bean 的 serialVersionUID

无论我做什么,类加载器都没有正确包装或加载。

有人知道什么会导致这样的问题吗?我不知道还要尝试什么,因此非常感谢任何建议!

提前致谢!

问候, 罗伯特

【问题讨论】:

  • 您说“Spring 将这些对象包装在代理中”。你是如何配置它来做到这一点的?什么机制?什么配置?
  • 嗯,没有配置,因为 spring 默认情况下会这样做。这对于在没有 setter 方法的情况下实现属性自动装配等事情是必要的。
  • Spring 默认不这样做。某事,某处,你告诉它这样做。通过字段注入自动装配是通过反射完成的,而不是代理。
  • 感谢您的回答。我没有提到的是我正在使用 Spring Security,它可能是代理的来源,因为它使用 Aspects 来实现方法安全。 spring 文档说 spring 中的代理要么是 JDK 动态代理,要么是 CGLIB 代理。我还尝试输出 bean 本身(h:outputText with value="#{customerBean})。这将打印具有正确类名和对象标识符的正确 Object-toString() 方法。因此访问 bean 本身是有效的,但是诸如 getCustomer() 方法之类的方法却没有。
  • 好的,现在我做了更多的研究,并试图思考我在哪里间接配置了代理。我使用带有@Transactional 注释的DAO 对象。根据文档,事务处理是通过代理完成的。我还在我的 bean(即 customerBean)的方法上添加了 @Transactional 注释。我删除了它,现在它可以工作了。但我想还是有问题,因为代理对象应该与包装对象具有相同的公共接口。

标签: java spring classloader tomcat7 proxy-classes


【解决方案1】:

我还使用 Tomcat 7、JSF 2、Spring 3、Spring Security 3。 我有同样的问题。更改编织配置没有帮助。

我的最终解决方案是在 spring 配置中添加一行:

<aop:aspectj-autoproxy proxy-target-class="true"/>  

你的类路径中需要 CGLIB。
希望这可以帮助某人。 :)

【讨论】:

    【解决方案2】:

    好的,我发现了如何使用 AspectJ 编织管理方法安全性。

    你至少需要使用 Spring-security 3.0.5,你需要在你的 spring-security.xml 中使用正确的模式,至少:
    http://www.springframework.org/schema/security/spring-security-3.0.5.xsd

    你需要添加 spring-security-aspects 作为依赖:

    <dependency>
       <groupId>org.springframework.security</groupId>
       <artifactId>spring-security-aspects</artifactId>             
       <version>3.0.5.RELEASE</version>
    </dependency>
    

    您可以在全局方法安全标签中添加新属性“mode”:

    <global-method-security pre-post-annotations="enabled" mode="aspectj"/>
    

    我认为您还必须在标准 Spring-configuration.xml 中添加启用 AspectJ 编织的标记:

    <context:load-time-weaver aspectj-weaving="on"/>
    

    摆脱(删除) aop-proxy 标签也有好处:

    <aop:aspectj-autoproxy proxy-target-class="true"/>
    

    此外,最好使用 Spring-security 3.1.0,但至少还必须使用 Spring 3.0.7。

    希望这会有所帮助:)

    【讨论】:

    • 我正在使用 Spring 4.3.4、Java 8 和 Weblogic 12.2.1.0,这个答案帮助我解决了javax.el.PropertyNotFoundException。谢谢@ondrej-bozek
    【解决方案3】:

    如果未正确配置加载时间编织,通常会发生这些错误。确保您不仅配置了加载时间编织器,而且还加载了适当的 java 代理,或者应用程序服务器为您完成了这项工作。

    有关如何配置此环境的更多信息,请参阅 spring 文档,例如chapter 7.8.4.6 Environment-specific configuration。虽然,这涵盖了 AOP 的加载时间波动主题,但对于 spring 的其他需要加载时间波动的部分的配置是相同的。

    【讨论】:

      【解决方案4】:

      尝试删除 customerBean 具有 oneToMany 字段的域。

      【讨论】:

        【解决方案5】:

        我认为你的 bean 实现了Serializable。我今天遇到了这个问题,Serializable 对代理做了一些奇怪的事情,我的方法都无法访问。摆脱 Serializable,它应该可以工作。

        【讨论】:

          猜你喜欢
          • 2012-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-05-25
          • 1970-01-01
          • 2012-01-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多