Spring Boot中使用@PreAuthorize触发NullPointerException问题排查
可能原因
代理机制引发依赖注入失效
Spring Security通过AOP实现方法级权限控制,当给方法添加@PreAuthorize时,Spring会为控制器类创建代理对象。如果你的控制器使用字段注入(@Autowired直接标注在字段上),且代理方式为JDK动态代理(要求类实现接口),代理对象本身的字段不会被注入,调用方法时就会出现依赖为null的情况。而另一个testMethod能正常工作,可能是该方法未直接使用字段注入的依赖,或者代理逻辑在该场景下未触发问题。方法安全配置的细节遗漏
Spring Boot 3.x版本需要在配置类上添加@EnableMethodSecurity(替代旧版的@EnableGlobalMethodSecurity)才能启用@PreAuthorize注解,虽然另一个方法能运行,但不排除部分代理逻辑在特定方法上出现异常。
解决方法
改用构造方法注入(推荐)
字段注入是Spring不推荐的方式,构造方法注入能确保依赖在对象实例化时就完成注入,代理对象也能正确转发调用到已初始化的目标对象:@RestController public class ProductController { private final ProductService productService; // 构造方法注入 public ProductController(ProductService productService) { this.productService = productService; } @PreAuthorize("hasAuthority('CLIENT')") @GetMapping("/products") public List<Product> getProducts() { return productService.findAll(); } }强制使用CGLIB代理
在Spring Security配置类上添加proxyTargetClass = true,强制Spring使用基于类的CGLIB代理(无需实现接口),规避JDK动态代理的字段注入问题:@Configuration @EnableMethodSecurity(proxyTargetClass = true) public class SecurityConfig { // 你的安全配置代码 }检查控制器基础配置
确保ProductController类上标注了@RestController或@Controller,且所在包被Spring组件扫描覆盖(Spring Boot默认扫描启动类所在包及子包)。
内容的提问来源于stack exchange,提问作者Smaillns

