You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为Spring控制器添加@Transactional注解引发404错误的原因排查

解决Spring控制器加@Transactional后返回404的问题

问题根源

给控制器添加@Transactional后,Spring默认生成了JDK动态代理。JDK代理是基于接口实现的,代理类不会继承原控制器类上的@RestController、@RequestMapping等注解。而Spring MVC的AbstractHandlerMethodMapping在注册路由时,会通过isHandler方法检查Bean类是否带有@Controller/@RestController注解——代理类没有这些注解,因此无法通过检查,路由映射未被注册,最终所有请求返回404。

解决方案

1. 改用CGLIB代理(推荐)

CGLIB是基于类继承的代理方式,会完整保留原类的注解,让Spring MVC能正常识别控制器。

  • Java配置方式:
    在事务配置类中开启proxyTargetClass参数:

    @Configuration
    @EnableTransactionManagement(proxyTargetClass = true)
    public class TransactionConfig {
        // 配置事务管理器
        @Bean
        public PlatformTransactionManager transactionManager(DataSource dataSource) {
            return new DataSourceTransactionManager(dataSource);
        }
    }
    
  • XML配置方式:
    在Spring配置文件中设置proxy-target-class="true":

    <tx:annotation-driven proxy-target-class="true"/>
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    

2. 迁移@Transactional到业务层(更符合架构规范)

事务注解本来就应该放在业务逻辑层(Service)而非控制器层,这是分层架构的基本规范。把@Transactional从控制器类上移到对应的Service方法或类上,既解决了404问题,也让代码结构更合理。

3. 自定义HandlerMapping的检测逻辑

如果必须使用JDK代理,可以自定义RequestMappingHandlerMapping,修改isHandler方法,让它检测代理背后的目标类是否带有控制器注解:

@Configuration
public class WebMvcCustomConfig implements WebMvcConfigurer {
    @Bean
    public RequestMappingHandlerMapping requestMappingHandlerMapping() {
        return new RequestMappingHandlerMapping() {
            @Override
            protected boolean isHandler(Class<?> beanType) {
                // 获取代理对应的目标类
                Class<?> targetClass = AopProxyUtils.getSingletonTargetClass(beanType);
                if (targetClass != null) {
                    beanType = targetClass;
                }
                // 调用父类逻辑检查是否为控制器
                return super.isHandler(beanType);
            }
        };
    }
}

4. 给控制器接口添加注解(不推荐)

如果控制器类实现了某个接口,可以在接口上添加@RestController和@RequestMapping注解,这样JDK代理类实现该接口后,就能被Spring MVC识别。但这种方式不符合常规编码规范,容易引起混淆,不建议使用。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:38:25