Spring @Transactional timeoutString的SpEL失效,如何实现事务超时可配置?
方法级事务超时可配置的解决方案
问题原因
你碰到的问题本质是:AnnotationTransactionAttributeSource虽实现了EmbeddedValueResolverAware接口,但Spring容器默认不会为其注入StringValueResolver,导致@Transactional注解的timeoutString属性里的SpEL表达式无法被解析执行。
可行解决方案
方案一:用BeanPostProcessor注入StringValueResolver
编写一个BeanPostProcessor,在容器初始化AnnotationTransactionAttributeSource实例时,手动注入StringValueResolver:
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.EmbeddedValueResolverAware; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringValueResolver; import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; @Configuration public class TransactionAttributeSourceProcessor implements BeanPostProcessor { private final StringValueResolver stringValueResolver; public TransactionAttributeSourceProcessor(StringValueResolver stringValueResolver) { this.stringValueResolver = stringValueResolver; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof AnnotationTransactionAttributeSource annotationSource) { annotationSource.setEmbeddedValueResolver(stringValueResolver); } return bean; } }
配置这个类后,原有的@Transactional(timeoutString = "#{transactionProperties.myServiceTransactionTimeout.getSeconds()}")就能正常解析SpEL,读取配置的超时时间。
方案二:自定义TransactionAttributeSource替换默认实现
直接创建自定义的TransactionAttributeSource实例并注入StringValueResolver,让Spring优先使用这个实例:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringValueResolver; import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource; import org.springframework.transaction.interceptor.TransactionAttributeSource; @Configuration public class CustomTransactionConfig { @Bean public TransactionAttributeSource transactionAttributeSource(StringValueResolver stringValueResolver) { AnnotationTransactionAttributeSource source = new AnnotationTransactionAttributeSource(); source.setEmbeddedValueResolver(stringValueResolver); return source; } }
这种方式直接替换了Spring默认的TransactionAttributeSource,同样能让SpEL表达式生效。
验证
配置完成后启动应用,调用MyService.exampleTransaction()方法,可通过调试或查看事务相关日志确认超时时间已正确加载配置值。
内容的提问来源于stack exchange,提问作者D. Kellenberger
相关产品推荐
相关产品推荐

