【问题标题】:Spring DefaultAdvisorAutoProxyCreator with @Transactional causing problemsSpring DefaultAdvisorAutoProxyCreator 与 @Transactional 导致问题
【发布时间】:2012-08-07 17:38:14
【问题描述】:

我正在开发一个 Spring MVC 项目并尝试集成 Apache Shiro 以提高安全性。一切都很顺利,直到我意识到 Hibernate 在一次查询后过早地关闭了会话/连接并导致了一个 lazyinit 异常。毫不奇怪,我所做的应该在事务中完成,这样会话就不会关闭。

两难境地……

  1. 我尝试将 @Transactional 放在我的控制器方法上,但我得到了 404。查看我的日志,我可以看到,当 Spring 引导时,如果 @Transactional 注释在控制器中的任何方法上,它会忽略我的 HomeController 中的任何映射。

  2. 没有 @Transactional 并且它加载得很好,我可以看到 RequestMappingHandlerMapping bean 看到我的控制器中的所有 @RequestMapping 注释。

  3. 使用 @Transactional 但没有 DefaultAdvisorAutoProxyCreator,除了 Shiro 注释被忽略之外,它可以正常工作。

tldr: Shiro 需要 DefaultAdvisorAutoProxyCreator,但如果我创建了那个 bean,Spring 在使用 @Transactional 注释时会崩溃。

我正在寻求帮助,因为我现在完全不知道如何进行。

【问题讨论】:

    标签: spring aop shiro


    【解决方案1】:

    这通常是因为当您将@Transactional 放在一个方法上时,Spring 会为该 bean 创建一个动态代理 - 如果 bean 实现了一个接口,则基于该接口创建动态代理,否则将使用 CGLIB 来创建代理.

    我猜你的问题是因为你的控制器可能基于某个接口,或者你正在基于基类扩展它。这最终会基于该接口创建一个代理,因为当需要为您的请求创建映射时,Spring MVC 可能无法从您的 bean 中找到您的映射。

    修复可能有几个:

    一个。您可以尝试强制代理基于 CGLIB 进行交易:

    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    

    b.您可以使用纯 Aspectj,加载时编织或编译时编织

    c。您可以将@Transactional 移动到一个服务中(它有一个接口)并将控制器的调用委托给服务,这样可以避免控制器上的@Transaction

    【讨论】:

    • 好吧,那可能是因为正在创建的CGLIB代理没有携带@RequestMapping注解,那么推荐肯定会在上面c点。
    • 抱歉,不小心提交了之前的评论,然后将其删除。我没有 HomeController 扩展或实现任何接口,所以可能不是这样,尽管从那时起我就是。当 DefaultAdvisorAutoProxyCreator 为 Shiro 试图绑定的切入点创建 AOP 代理(纯 java,而不是 cglib)时,可能会发生类似的事情?有没有办法为所有代理指定 cglib?
    • 哦,好吧 - proxy-target-class="true" 强制为 @Transaction 场景使用基于 CGLIB 的代理。
    • 只是想更新,让每个人都可以看到选项 B 解决了我的问题。我试图完全不必使用aspectj,但在Shiro/Apache 创建代理之前,我无法让RequestMappingHandlerAdapter 映射@RequestMapping。即使使用 cglib 也无法正确读取。添加 spring-aspects 并使用 可以让它工作得很好。感谢您的帮助!
    猜你喜欢
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 2012-07-13
    • 2014-07-26
    • 1970-01-01
    • 2021-12-30
    • 2013-01-13
    • 2019-02-15
    相关资源
    最近更新 更多