Spring Bean加载与测试初始化:如何尽早执行foo.setBar(bar)?
解决思路
1. 自定义BeanPostProcessor(推荐,上下文启动阶段执行)
这是最直接的方式,能在Bean初始化完成后立即执行赋值操作,属于Spring上下文启动流程中的核心环节,比测试类的setup方法早得多。
创建一个自定义的Bean后置处理器,在Foo实例初始化后注入Bar:
@Component public class TestBeanPostProcessor implements BeanPostProcessor { @Autowired private Bar bar; @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Foo) { ((Foo) bean).setBar(bar); } return bean; } }
然后在测试类中通过@Import(TestBeanPostProcessor.class)把这个处理器加入测试上下文,或者直接放在测试类所在的包下让Spring扫描到。
2. 利用SmartInitializingSingleton接口
这个接口的afterSingletonsInstantiated方法会在所有单例Bean初始化完成后立即执行,时机早于测试类的setup方法。
可以在测试类中定义一个内部Bean实现该接口:
@ActiveProfiles(value = "test") @SpringBootTest(classes = AbcApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @Import(TestSingletonInitializer.class) class AbcTest extends Specification { // 测试用例... } @Component class TestSingletonInitializer implements SmartInitializingSingleton { @Autowired private Foo foo; @Autowired private Bar bar; @Override public void afterSingletonsInstantiated() { foo.setBar(bar); } }
3. 自定义TestExecutionListener
针对Spring Boot测试场景,可以自定义测试执行监听器,在测试实例依赖注入完成后立即执行赋值,时机比测试类的setup方法更早。
public class FooBarInitListener extends AbstractTestExecutionListener { @Override public void prepareTestInstance(TestContext testContext) throws Exception { Foo foo = testContext.getApplicationContext().getBean(Foo.class); Bar bar = testContext.getApplicationContext().getBean(Bar.class); foo.setBar(bar); } }
然后在测试类上添加@TestExecutionListeners(listeners = FooBarInitListener.class, mergeMode = MergeMode.MERGE_WITH_DEFAULTS),确保默认的监听器(比如依赖注入的)依然生效。
4. 修改Foo源码(若允许)
如果能修改Foo的自动配置源码,可以直接通过@DependsOn保证Bar先初始化,再用@PostConstruct完成赋值:
// 修改Foo类 @Component @DependsOn("bar") // 确保Bar先于Foo初始化 public class Foo { private Bar bar; @Autowired public void setBar(Bar bar) { this.bar = bar; } // 或者用@PostConstruct @PostConstruct public void init() { // 这里可以直接使用bar,因为@DependsOn保证了Bar已初始化 } }
这种方式最简洁,但前提是你有权限修改自动配置的Bean源码。
内容的提问来源于stack exchange,提问作者IceMajor
相关产品推荐
相关产品推荐

