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

集成测试中@PreAuthorize注解导致注入Bean为空的问题排查

解决Spring Boot Starter测试中@PreAuthorize导致控制器Bean为空的问题

问题根源

当给控制器方法添加@PreAuthorize、@Secured或@RolesAllowed这类方法级安全注解时,Spring Security会通过AOP为控制器生成代理对象。如果控制器未实现接口,默认会使用CGLIB代理,但如果配置或环境触发了JDK动态代理(基于接口的代理方式),代理对象不会继承原控制器类的字段,就会出现注入的Bean为空的情况。另外,代理初始化时机不当也可能导致依赖注入未完成。

具体解决办法

1. 强制使用CGLIB代理

在测试配置类或starter的自动配置类中,开启CGLIB代理模式:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class TestSecurityConfig {
    // 自定义安全配置逻辑
}

proxyTargetClass = true会强制Spring使用CGLIB生成代理,代理对象会继承原控制器的所有字段,注入的Bean就能正常访问。

2. 改用构造函数注入

避免在控制器字段上直接使用@Autowired,改用Spring官方推荐的构造函数注入方式,确保代理创建前完成依赖注入:

@RestController
public class TestController {
    private final ApplicationContext applicationContext;

    // Spring 4.3+无需添加@Autowired,自动识别构造函数注入
    public TestController(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @PreAuthorize("hasRole('ADMIN')")
    @GetMapping("/test")
    public String test() {
        // 正常使用applicationContext
        return "success";
    }
}

3. 检查测试类配置

确保测试类正确加载Spring上下文,配置必要的测试注解:

@SpringBootTest(classes = TestApplication.class)
@AutoConfigureMockMvc
public class SecurityIT {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testAuthorizedRequest() throws Exception {
        mockMvc.perform(get("/test")
                        .with(user("admin").roles("ADMIN")))
                .andExpect(status().isOk());
    }
}

@SpringBootTest需指定正确的启动类,@AutoConfigureMockMvc会自动配置MockMvc,保证测试上下文完整初始化所有Bean和代理对象。

4. 调整自动配置加载顺序

如果starter的自动配置类有依赖顺序要求,让它在Spring Security自动配置之后加载,避免代理逻辑提前初始化导致依赖注入未完成:

@AutoConfigureAfter(SecurityAutoConfiguration.class)
@Configuration
public class MySecurityAutoConfiguration {
    // starter的自动配置逻辑
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:52:58