Spring Boot 在Controller使用@Transactional注解导致@RequestMapping失效
2017-11-21 17:35
1706 查看
笔者在基于 Spring Boot 开发服务框架时,想要在 Controller 层使用 @Transactional 注解引入 Spring 的事务管理,但是却遇上了很奇葩的问题。
例如以下代码,给 Controller 类的add方法加上@Transactional,这个 Controller 类使用 @RestController 注解,类名上也配置了 @RequestMapping,
后来笔者重新创建了一个 Controller 类进行问题复现,最终发现原来是上面的 Controller 类实现了笔者定义的另一个接口,类定义如下
解决方法:
笔者又引入了 cglib 和 asm 两个依赖,并且在程序入口处增加了 @EnableAsync 注解,代码如下。引入 cglib 后 @RequestMapping 和 @Transactional 均可以正常使用,抛出异常后事务可以回滚。
最后附上 Maven 依赖定义
此外 Spring 使用 4.3.12.RELEASE,Maven项目直接继承(parent) spring-boot-starter-web, 版本 1.5.8.RELEASE,并增加 spring-tx,数据源依赖 druid,版本为 1.1.5,Java 8编译
例如以下代码,给 Controller 类的add方法加上@Transactional,这个 Controller 类使用 @RestController 注解,类名上也配置了 @RequestMapping,
@RequestMapping(KiEntityActionName.ACTION_ADD + URL_EXTENSION) @Transactional( value = KiDataSourceConfig.TRADE_TX_MANAGER, timeout = 30, isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = Exception.class) @Override public Object add() { Map<String, Object> params = new HashMap<>(); params.put("sellerId", 12); params.put("buyerId", 2); Object rtnData = this.bizService.execute(KiEntityActionEnum.ADD, params); return rtnData; }然后启动应用程序,在控制台输出信息里,属于该类的所有 RequestMapping 全都不见了,正常应该出现如下信息,可以看到 "Mapped ****** " 等内容,表示使用@ReqeustMapping 配置的URL地址映射,但是该问题的奇葩之外在于,给任意方法加上 @Transactional 后,所有的映射就全部注入失败了,给整个类加上 @Transactional 也是同样问题,交换注解的顺序也没有用。
2017-11-21 17:32:00.431 INFO 3953 --- [ main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@5f058f00: startup date [Tue Nov 21 17:31:58 CST 2017]; root of context hierarchy 2017-11-21 17:32:00.487 INFO 3953 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/example/add.service]}" onto public java.lang.Object com.emulian.kiff.controller.KiExampleController.add() 2017-11-21 17:32:00.487 INFO 3953 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/example/one.service]}" onto public java.lang.Object com.emulian.kiff.controller.KiExampleController.one() 2017-11-21 17:32:00.488 INFO 3953 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/example/hello.service]}" onto public java.lang.String com.emulian.kiff.controller.KiExampleController.hello() 2017-11-21 17:32:00.488 INFO 3953 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/example/lst.service]}" onto public java.lang.Object com.emulian.kiff一开始没有意识到是 @Transactional 注解的问题,找了很长时间错误原因。
后来笔者重新创建了一个 Controller 类进行问题复现,最终发现原来是上面的 Controller 类实现了笔者定义的另一个接口,类定义如下
@RestController @RequestMapping(KiBizEntityName.ENTITY_EXAMPLE) public class KiExampleController extends KiControllerAbstract implements KiControllerInterface { }也就是比一般定义的 Controller 多了一个 implements 的声明(继承抽像类不影响),这个时候虽然不影响 @RequestMapping 的注入,但是类内如果再增加 @Transactional 的话,整个类的所有注入就全部失效了,应该是 Spring 注入代理使用了 JDK 默认代理的原因。
解决方法:
笔者又引入了 cglib 和 asm 两个依赖,并且在程序入口处增加了 @EnableAsync 注解,代码如下。引入 cglib 后 @RequestMapping 和 @Transactional 均可以正常使用,抛出异常后事务可以回滚。
@EnableTransactionManagement @SpringBootApplication /** * This @SpringBootApplication is a convenience annotation that adds all of the following: * @Configuration tags the class as a source of bean definitions for the application context. * @EnableAutoConfiguration tells Spring Boot to start adding beans based on classpath settings, other beans, and various property settings. * @EnableWebMvc Normally you would add @EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet. * @ComponentScan tells Spring to look for other components, configurations, and services in the hello package, allowing it to find the controllers. * */ @EnableAsync(proxyTargetClass = true) public class KiApplication { public static void main(String[] args) throws Exception { SpringApplication.run(KiApplication.class, args); } }其实笔者增加 @EnableAsync 注解 也是因为看到如下的错误信息,配置注解的 proxyTargetClass=true 从而强制使用 cglib 来实现注入
*************************** APPLICATION FAILED TO START *************************** Description: The bean 'kiExampleBizService' could not be injected as a '*.*.kiff.service.biz.KiExampleBizService' because it is a JDK dynamic proxy that implements: *.*.kiff.interfaces.service.biz.KiBizServiceInterface Action: Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching. Process finished with exit code 1
最后附上 Maven 依赖定义
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.4</version> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>5.1</version> </dependency>
此外 Spring 使用 4.3.12.RELEASE,Maven项目直接继承(parent) spring-boot-starter-web, 版本 1.5.8.RELEASE,并增加 spring-tx,数据源依赖 druid,版本为 1.1.5,Java 8编译
相关文章推荐
- 使用模态视图导致pushViewController失效的解决方法
- Spring Boot 中使用 @Transactional 注解配置事务管理
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
- (32)Spring Boot使用@SpringBootApplication注解,从零开始学Spring Boot
- spring,mybatis事务管理配置与@Transactional注解使用
- Spring3事务管理--使用@Transactional 注解
- spring,mybatis事务管理配置与@Transactional注解使用[转]
- spring mvc controller 各注解GET和POST 使用说明
- Spring注解@Componen、@Repository@Service、@Controller区别与Spring2.5中使用注解装配属性and组件自
- 使用@Controller注解为什么要配置<mvc:annotation-driven />
- spring,mybatis事务管理配置与@Transactional注解使用
- SpringMVC常用注解實例詳解1:@Controller,@RequestMapping,@RequestParam,@PathVariable
- Aix普通用户使用bash导致ftp失效
- spring,mybatis事务管理配置与@Transactional注解使用
- SprinMVC-高级参数绑定、@RequestMapping注解、Controller方法返回等
- 使用@Controller注解为什么要配置<mvc:annotation-driven />
- 使用spring注解@Controller @Service @Repository简化配置
- 使用.NET Framework Client Profile 导致的引用失效
- 使用@Controller注解为什么要配置<mvc:annotation-driven />
- spring事物配置,声明式事务管理和基于@Transactional注解的使用