- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个@Transactional @Controller
,但它的方法在没有事务的情况下被 Spring MVC 框架调用。在异常跟踪中,我没有找到拦截调用的事务顾问:
org.hibernate.HibernateException: No Session found for current thread
org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:106)
org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:1014)
org.example.businesslogic.MyController.userLoggedIn(SwiperRest.java:48)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:483)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:749)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:689)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:938)
另一方面,日志清楚地表明 Controller 方法被检测为事务性的:
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'metaDataSourceAdvisor'
DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'MyController.userLoggedIn' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.a.f.a.InfrastructureAdvisorAutoProxyCreator - Creating implicit proxy for bean 'myController' with 0 common interceptors and 1 specific interceptors
DEBUG o.s.a.f.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [org.example.businesslogic.MyController@7c0f1b7c]
DEBUG o.s.a.f.CglibAopProxy - Unable to apply any optimisations to advised method: public java.lang.String org.example.businesslogic.MyController.userLoggedIn(java.lang.String,java.lang.String)
DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'MyController.locationProfiles' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
DEBUG o.s.a.f.CglibAopProxy - Unable to apply any optimisations to advised method: public java.util.List org.example.businesslogic.MyController.locationProfiles(java.lang.String)
来自 Controller 类的片段:
@Transactional
@Controller
@RequestMapping("/zendor")
public class MyController
{
@Autowired private SessionFactory sf;
@RequestMapping(method=POST, value="userLoggedIn")
public @ResponseBody String userLoggedIn(@RequestParam String u_id, @RequestParam String d_id) {
Session hb = sf.getCurrentSession();
...
}
}
这是我的 web 应用程序初始化类,我没有 web.xml
:
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer
{
@Override
protected Class<?>[] getRootConfigClasses() { return new Class[] { RootConfig.class }; }
@Override
protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; }
@Override
protected String[] getServletMappings() { return new String[] { "/" }; }
@Override public void onStartup(ServletContext ctx) throws ServletException {
ctx.setInitParameter("spring.profiles.active", "production");
super.onStartup(ctx);
}
}
这是引用的根配置:
package org.example.config;
@Configuration
@ComponentScan
public class RootConfig
{
}
它与这些在同一个包中,由默认组件扫描范围拾取:
@Configuration
@EnableWebMvc
@ComponentScan("org.example.businesslogic")
public class WebMvcConfig extends WebMvcConfigurationSupport
{
}
@Configuration
@EnableTransactionManagement
@ComponentScan("org.example.businesslogic")
public class DataConfig implements TransactionManagementConfigurer
{
@Autowired private DataSource dataSource;
...
}
当 Spring-test 的 SpringJUnit4ClassRunner
使用相同的配置时,方法会得到建议并且事务会工作。
我还尝试将 userLoggedIn
方法提取到 @Autowired
@Transactional @Component
,但结果是相同的。
我应该从哪个方向研究来解决这个问题?
我在 Spring 4.0.5 上。
关键问题是我的根配置也引入了所有其他配置类,包括 WebMvcConfig
,它作为子 servlet 配置再次加载。
非常违反直觉,只有当我删除 servlet 配置类,替换
@Override
protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; }
与
@Override
protected Class<?>[] getServletConfigClasses() { return null; }
这直接违背了文档:可能不为空或 null
。如果我反其道而行之,为 rootConfigClasses
提供 null
,为 servletConfigClasses
提供 RootConfig
,那么一切都将更加失败,因为“找不到 servlet 上下文。”。
在没有根应用程序上下文的情况下发生的故障已追溯到 Spring Web Security,显然必须在根级别配置它才能被 SecurityWebApplicationInitializer
获取,因为这似乎在执行根应用程序上下文已经存在但网络应用程序上下文不存在的阶段。所以我的问题解决方案是在根和 webapp 上下文之间引入一个分离,其中 root 加载安全和 webapp 一切。
最佳答案
如果你还没有读过它们
同样适用于AbstractAnnotationConfigDispatcherServletInitializer
的 getRootConfigClasses()
和 getServletConfigClasses()
.基本上就是WebApplicationInitializer
将构造(并注册)一个 ContextLoaderListener
用AnnotationConfigWebApplicationContext
注册所有 @Configuration
(和其他 @Component
注释)类来自 getRootConfigClasses()
.然后它将构造并注册一个DispatcherServlet
。所有@Configuration
(和其他...)类来自 getServletConfigClasses()
.
作为Servlet生命周期的一部分,容器首先会初始化所有ServletContextListener
对象。这意味着 ContextLoaderListener
将首先加载 refresh
AnnotationConfigWebApplicationContext
那是给它的(如果它还没有被刷新,理想情况下它不应该被刷新)。它还会把这个 ApplicationContext
作为 ServletContext
中的一个属性.
然后容器会初始化注册的DispatcherServlet
.这里有一些更多的阅读
基本上,DispatcherServlet
将refresh
ApplicationConfigWebApplicationContext
它通过首先将其父级设置为 ApplicationContext
来接收在ServletContext
(由 ContextLoaderListener
设置),如果有的话。
然后它将开始从其 ApplicationContext
中挑选 bean 设置 MVC 堆栈、 Controller 、处理程序方法、拦截器等。默认情况下,它只会查找其处理程序 bean,@Controller
bean ,在ApplicationContext
它加载了,而不是它的父级。
你好像做了什么
@Override
protected Class<?>[] getServletConfigClasses() { return new Class[] { WebMvcConfig.class }; }
和
@Override
protected Class<?>[] getRootConfigClasses() { return new Class[] { RootConfig.class }; }
在这种情况下,ContextLoaderListener
将加载 RootConfig
这将创建一堆 beans,包括你的 @Controller
@Transactional
将建议的类(class)配置。
DispatcherServlet
然后将加载 WebMvcConfig
它有自己的 @ComponentScan
这将创建新的 @Controller
bean ,但这些不会被建议,因为没有 TransactionInterceptor
已注册(在此上下文中没有 @EnableTransactionManagement
)。 DispatcherServlet
然后将尝试找到所有 @Controller
bean(和其他有 @RequestMapping
方法的 bean)在它自己的 ApplicationContext
中.它会找到这些 @Controller
不建议使用的 bean 类。这些是它将注册为处理程序的那些,而不是由 ContextLoaderListener
加载的那些.
如果您进一步查看日志,您应该会看到正在创建一个新的 Controller bean。
建议:
Controller 不是整个应用程序都应该访问的组件。只有 DispatcherServlet
应该关心他们。将它们放在 servlet 上下文中。
现在我显然不了解您的整个应用程序,但我建议您将所有事务逻辑从处理程序方法中重构到一些 @Service
中。方法。它将使您更容易维护您的配置并使您的 Controller 更像 Controller ,即。委托(delegate)给模型。
关于java - 即使在日志中看到 "adding transactional method",事务顾问也不会拦截方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24367503/
我刚开始使用新的拦截方法,有一个基本问题,想知道如何在一个测试中链接下面的两个断言。 cy.intercept('GET', '/states').as('states'); cy.reload(tr
我有一个标签控件的自定义版本(使用用户控件构建)。在设计器中工作时,我想截取 Name 属性的设置(在属性面板中)并使用它来生成 Text 属性。也就是说,如果我在属性面板的 Name 属性中输入“l
嗨,我想通过 soapUI 解析 ssl soap 消息,而我试图通过 HttpMonitor 进行拦截它显示在异常下方 ERROR:Exception in request: javax.net.s
是否有可能从某个任意层拦截反向梯度,修改其值并继续反向传播回到网络的开始,根据您提供的修改后的梯度值更新所有先前层的反向梯度? 我知道你可以directly modify the gradients
我可以从什么 dll 中获得 Intercept 的扩展?我从 http://github.com/danielmarbach/ninject.extensions.interception 添加了
我有一个实现 onCreateOptionsMenu 方法的顶级 TabHost。我希望子 Activity (选项卡内的子 Activity )能够通过 onOptionsItemSelected
我在尝试反序列化 URL 时遇到此错误 Caused by: java.net.MalformedURLException: no protocol: www.boo.com at java.
首先,我是 Spring 的新手,这是我第一次尝试使用 Spring 编写基于 REST 的应用程序。 我计划在请求参数和响应中使用 Json。这让我想到两个问题。 有没有办法将 products="
在我基于 j_security_check 的登录表单中登录时一切正常。在这种情况下,我看到 JSESSIONID cookie 中的路径具有来自 URL 的值。但是当另一个登录页面构造动态表单(它正
我有一个我一直致力于下载文件的程序。一切正常,除非用户使用 AVG。奇怪的是,为了解决这个问题,似乎必须禁用 AVG 的“电子邮件保护”;将我的程序或 JRE 添加到异常(exception)列表不起
我正在寻找一种方法来挂接 SMSManager 或较低级别的机制,以便我可以在发送任何外发 SMS 消息之前拦截、读取和取消它们。 最佳答案 迟到总比不到好:) 我已经在这上面花了 2 天...并且不
我已成功拦截对 read() 的调用, write() , open() , unlink() , rename() , creat()但不知何故截获完全相同的语义stat()没有发生。我已经使用 L
阿里云ECS通过安全组屏蔽/拦截/阻断特定IP对云服务器的访问 所适用的场景: 通过安全组屏蔽、拦截、阻止特定IP对用户云服务器的访问,或者屏蔽IP访问服务器的特定端口。 配置的方法: 1、
我希望能够在类本身的构造函数中代理类的所有方法。 class Boy { constructor() { // proxy logic, do something before
使用 ajax 请求可以使用以下代码完成: let oldXHROpen = window.XMLHttpRequest.prototype.open; window.lastXhr = ''; wi
我想“拦截”/更改将 OData 与 Web API 一起使用时生成的 OData 查询..但我不完全确定如何“提取”生成的查询..我假设 OData 过滤器、扩展和更多一些如何生成某种表达式树或某种
当 JUnit 中的断言失败时,我想做一些“自己的事情”。我想要这个: public class MyAssert extends org.junit.Assert { // @Overrid
如何拦截 PartialFunction?例如在 Actor 中,如果我只想打印进入以下接收方法的所有内容,然后再将其传递给流程方法: class MyActor extends Actor {
我们正在使用 fluentvalidation(带有服务堆栈)来验证我们的请求 DTO。我们最近扩展了我们的框架以接受“PATCH”请求,这意味着我们现在需要仅在补丁包含要验证的字段时才应用验证。 我
我有一个作为 excel 插件运行的 WPF 应用程序,它有这样的可视化树 精益求精 元素主机 WPF 用户控件 WPF 色带条控件 现在,在 excel 中加载插件时,不会启用位于 WPF 功能区栏
我是一名优秀的程序员,十分优秀!