2012-08-10 108 views
2

我正在开发一个Spring MVC项目,并试图整合Apache Shiro的安全性。一切都在顺利进行,直到我意识到Hibernate在一次查询之后过早地关闭会话/连接并导致lazyinit异常。毫不奇怪,我在做的事情应该在交易中完成,所以会议不会结束。SpringTransactionAdvisorAutoProxyCreator与@Transactional导致问题

困境...

  1. 我试图把@Transactional我控制器的方法,但我得到404的即可。看看我的日志,我可以看到,当Spring引导时,如果@Transactional注释位于控制器内的任何方法上,它将忽略HomeController中的任何映射。

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

  3. 使用@Transactional但没有DefaultAdvisorAutoProxyCreator,它的工作原理除了Shiro注释被忽略。

tldr:四郎需要DefaultAdvisorAutoProxyCreator的,但如果我创建一个豆,春天使用@Transactional注释时炸毁。

我在寻求帮助,因为我完全处于如何在这一点上进行的损失。

回答

3

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

你的情况的问题,我猜是因为你可能已经基于你的控制器在某个接口上,或者你正在扩展它基于一个基类。这就结束了创建一个基于该接口的代理,因为这个时候需要创建映射的时候,Spring MVC可能无法从你的bean中找到你的映射。

修复可能是几个:

a。您可以尝试强制代理根据CGLIB进行交易:

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

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

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

+0

好吧,可能那么因为正在创建的CGLIB代理不是携带@RequestMapping注释,推荐肯定会是上面的c点。 – 2012-08-10 16:21:37

+0

对不起,意外提交了以前的评论,然后将其删除。我没有HomeController扩展或实现任何接口,所以它可能不是这样,虽然从那时起我是。也许类似的情况发生在DefaultAdvisorAutoProxyCreator为Shiro试图绑定的切入点创建AOP代理(纯java,而不是cglib)时?有没有办法为所有代理指定cglib? – 2012-08-10 16:24:41

+0

噢,好吧 - 'proxy-target-class =“true”'强制执行@Transaction方案的基于CGLIB的代理。 – 2012-08-10 19:54:37