如何将 AOP 建议应用于 ConstraintValidator在春天?
我正在尝试在 Spring 3.0.x 下编写自己的 Validator(根据 JSR-303 规范)。
我用 @Transactional
注释了 isValid(Serialized, CosntraintValidatorContext)
方法,但似乎事务建议并未应用于此方法 - 当 isValid()调用
方法,调用 sessionFactory.getCurrentSession()
会创建异常:
org.hibernate.HibernateException:没有 Hibernate Session 绑定到线程,并且配置不允许在此处创建非事务性会话
我在同一个 中有一个
bean 注入没有问题。我当前的解决方法是使用 @Autowired
sessionFactory
>ValidatoropenSession()
而不是 getCurrentSession()
,但这涉及我希望避免的手动事务管理。
在我的验证器 bean 的构造函数中进行堆栈跟踪,看来我的 Validator bean 是通过调用 osbfsAbstractAutowireCapableBeanFactory.createBean() 来构造的。我认为这意味着工厂能够填充我的 Validator
中的 @Autowired
字段,但它似乎没有应用任何事务建议?
预先感谢您对此事的任何帮助。
编辑:如果有任何帮助,我已经包含了记录在构造函数中的部分堆栈跟踪(通过 create new Exception()
):
at com.mydomain.validators.UniqueValidator.<init>(UniqueValidator.java:49) ~[UniqueValidator.class:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [na:1.6.0_20]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) [na:1.6.0_20]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) [na:1.6.0_20]
at java.lang.reflect.Constructor.newInstance(Constructor.java:513) [na:1.6.0_20]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:74) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:958) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:286) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory.getInstance(SpringConstraintValidatorFactory.java:50) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.validator.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:192) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:171) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:113) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:334) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:278) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:260) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:213) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:86) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.DataBinder.validate(DataBinder.java:692) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:807) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
事务配置似乎是正确的(STS IDE 报告isValid()
方法由事务管理器通过 org.springframework.transaction.interceptor.TransactionInterceptor.invoke
(带有 @Component
注释)正确建议在验证器本身)),但我的理解是,如果验证 bean 是在 Spring 容器的正常生命周期之外创建的,那么在数据绑定期间完成验证时,将无法正确应用建议。
I am attempting to write my own Validator
(as per the JSR-303 specification) under Spring 3.0.x.
I annotated the isValid(Serializable, CosntraintValidatorContext)
method with @Transactional
, but it seems that transactional advice is not being applied to this method - when the isValid()
method is invoked, a call to sessionFactory.getCurrentSession()
creates the Exception:
org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
I have an @Autowired
sessionFactory
in the same Validator
bean which is injected without issues. My current workaround is to use openSession()
instead of getCurrentSession()
, but that involves manual transaction management which I would prefer to avoid.
Doing a stack trace in the constructor of my validator bean, it seems that my Validator
bean is being constructed via a call to the o.s.b.f.s.AbstractAutowireCapableBeanFactory.createBean()
. I assume this means that the factory is capable of populating @Autowired
fields in my Validator
, but it seems that it is not applying any transactional advice?
Thanks in advance for any help on this matter.
EDIT: If it is of any help, I have included a partial stacktrace (via create new Exception()
) that is logged in the constructor:
at com.mydomain.validators.UniqueValidator.<init>(UniqueValidator.java:49) ~[UniqueValidator.class:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) [na:1.6.0_20]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) [na:1.6.0_20]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) [na:1.6.0_20]
at java.lang.reflect.Constructor.newInstance(Constructor.java:513) [na:1.6.0_20]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:126) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:74) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:958) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:911) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:485) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:286) [spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory.getInstance(SpringConstraintValidatorFactory.java:50) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.hibernate.validator.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:192) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:171) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:113) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:334) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:278) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:260) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:213) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) [hibernate-validator-4.0.2.GA.jar:4.0.2.GA]
at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:86) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.validation.DataBinder.validate(DataBinder.java:692) [spring-context-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.doBind(HandlerMethodInvoker.java:807) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:359) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171) [spring-web-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414) [spring-webmvc-3.0.5.RELEASE.jar:3.0.5.RELEASE]
Transactional configuration appears to be correct (the STS IDE reports that the isValid()
method is properly advised by the transactional manager by org.springframework.transaction.interceptor.TransactionInterceptor.invoke
(with an @Component
annotation on the Validator itself)), but my understanding is that if the validation bean is created outside the normal lifecycle of the Spring container, then the advice will not be properly applied when validation is done during data binding.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否已将
代码添加到您的配置中?
have you added the
code into your configuration?