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

添加@PreAuthorize注解后Service注入为null的原因排查

问题原因及解决方案

核心原因

你的控制器方法使用了private修饰符,而Spring Security的@PreAuthorize注解依赖Spring AOP实现权限拦截,AOP机制无法对private方法进行代理增强:

  • JDK动态代理只能代理接口的public方法;
  • CGLIB代理虽然可以继承目标类,但也无法拦截父类的private方法(子类无法访问父类私有方法)。

添加@PreAuthorize后,Spring尝试为UserController生成代理类以实现权限校验,但由于目标方法是private,代理逻辑无法生效,最终导致请求调用的对象并非Spring容器中已完成依赖注入的Bean实例,因此userService为null。

移除@PreAuthorize后,Spring MVC通过反射直接调用控制器的private方法(虽然不规范,但反射可访问私有方法),此时调用的是Spring容器中已注入依赖的Bean,所以能正常工作。

解决方案

将控制器中的方法修饰符改为public:

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserServiceImpl userService;

    @Autowired
    public UserController(UserServiceImpl userService) {
        this.userService = userService;
    }

    @PutMapping
    @PreAuthorize("hasAnyAuthority('ADMIN')")
    // 修改为public
    public ResponseEntity<ResultDto<UserDto>> updateUser(@RequestBody UserUpdateDto userUpdateDto) {
        return ResponseEntity.ok(new ResultDto<>(userService.updateUser(userUpdateDto)));
    }

    @GetMapping("/{id}")
    // 修改为public
    public ResponseEntity<ResultDto<UserDto>> getUserById(@PathVariable Long id) {
        return ResponseEntity.ok(new ResultDto<>(userService.findById(id)));
    }

    ...
}

额外说明

Spring MVC的控制器方法规范上必须是public的,即使反射能调用private方法,也会破坏Spring的代理机制(包括AOP、事务、权限等),引发各类异常问题,务必遵循规范使用public修饰控制器方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:22:07