如何实现仅在Spring完全配置完成后生效的@ConditionalOnMissingBean并处理@Controller
实现方案
1. 兜底Bean声明
针对ExternalAnnotatedRequestsModel添加缺省创建逻辑,通过@ConditionalOnMissingBean保证仅当用户未自定义该Bean时,才由Starter创建默认实例:
@Bean @ConditionalOnMissingBean public ExternalAnnotatedRequestsModel externalAnnotatedRequestsModel() { // 替换为你自己的默认实现构造逻辑 return new ExternalAnnotatedRequestsModel(); }
2. 可覆盖的Provider Bean声明
给ExternalRequestsProvider同样添加缺省注解,支持用户自定义覆盖,也可后续扩展配合@ConditionalOnProperty实现yaml配置切换:
@Bean @ConditionalOnMissingBean public ExternalRequestsProvider externalRequestsProvider(ConfigurableApplicationContext ctx) { return new AnnotationExternalRequestsProvider(ctx); }
3. 执行时机控制(满足所有Controller初始化完成后触发)
推荐通过实现SmartInitializingSingleton接口控制执行时机,该接口的回调会在Spring容器中所有单例Bean(包括所有@Controller/@RestController)完全初始化完成后触发,完美匹配你的需求:
@Configuration public class TestConfig implements SmartInitializingSingleton { private final ExternalAnnotatedRequestsModel model; private final ExternalRequestsProvider requestsProvider; // Spring 4.3+ 构造器注入无需加@Autowired,比字段注入更稳定 public TestConfig(ExternalAnnotatedRequestsModel model, ExternalRequestsProvider requestsProvider) { this.model = model; this.requestsProvider = requestsProvider; } @Bean @ConditionalOnMissingBean public ExternalAnnotatedRequestsModel externalAnnotatedRequestsModel() { return new ExternalAnnotatedRequestsModel(); } @Bean @ConditionalOnMissingBean public ExternalRequestsProvider externalRequestsProvider(ConfigurableApplicationContext ctx) { return new AnnotationExternalRequestsProvider(ctx); } @Override public void afterSingletonsInstantiated() { // 此时所有Controller已完全初始化,可安全执行扫描逻辑 Object processResult = requestsProvider.process(); // 替换为你自己的结果存入逻辑 model.setProcessResult(processResult); } }
如果不想修改配置类实现接口,也可以用监听上下文刷新事件的替代方案:
@EventListener(ContextRefreshedEvent.class) public void handleContextRefreshed() { Object processResult = requestsProvider.process(); model.setProcessResult(processResult); }
内容的提问来源于stack exchange,提问作者Goncalo Condeco
相关产品推荐
相关产品推荐

