从Spring XML迁移到SpringBoot:如何基于现有Bean创建Bean列表
最优方案与问题解答
一、直接调用@Bean方法的问题
你当前代码里直接调用user()会报错,因为该方法需要传入basic参数;更关键的是,即便手动传参,这种方式无法保证使用的是Spring容器管理的单例Bean(除非是在同一个@Configuration类中调用被代理的@Bean方法,但代码可读性差,不推荐)。
二、构建searches列表的最优方案
根据你原XML的逻辑(basic是抽象模板,列表包含基于它构建的roles、simple、user三个Bean),推荐两种简洁方案:
方案1:显式注入目标Bean(最直观,贴近原XML逻辑)
先调整basic的定义:原XML中basic是抽象Bean,仅作为模板,无需被Spring容器管理,因此将其改为私有工具方法,而非@Bean;然后在构建列表时,直接注入已经定义好的三个Parameter Bean:
@Configuration class WebConfig { // 私有模板方法,仅用于构建其他Parameter实例,不注册为Spring Bean private Parameter basic() { return Parameter.builder() .format(Pattern.compile("^[A-Za-z0-9]")) // 修正原正则表达式的语法错误 .maxLength(100) .build(); } @Bean public Parameter simple() { return basic().toBuilder() .field("attribute") .label("Attribute Name") // 修正原代码的拼写错误(Label -> label) .build(); } @Bean public Parameter user() { return basic().toBuilder() .field("product") .label("Product") .build(); } @Bean public Parameter roles() { return basic().toBuilder() .field("roles") .label("Roles") .build(); } // 注入三个Parameter Bean,构建searches列表 @Bean("searches") public List<Parameter> getSearch(Parameter simple, Parameter user, Parameter roles) { return List.of(simple, user, roles); } }
方案2:自动收集同类型Bean(适合Bean数量较多的场景)
如果后续会新增更多Parameter类型的Bean,可以通过Spring的自动注入特性,收集所有Parameter类型的Bean,再排除模板类(如果basic被注册为Bean的话):
@Configuration class WebConfig { @Bean("basic") public Parameter basic() { return Parameter.builder() .format(Pattern.compile("^[A-Za-z0-9]")) .maxLength(100) .build(); } @Bean public Parameter simple(@Qualifier("basic") Parameter basic) { return basic.toBuilder() .field("attribute") .label("Attribute Name") .build(); } @Bean public Parameter user(@Qualifier("basic") Parameter basic) { return basic.toBuilder() .field("product") .label("Product") .build(); } @Bean public Parameter roles(@Qualifier("basic") Parameter basic) { return basic.toBuilder() .field("roles") .label("Roles") .build(); } // 自动注入所有Parameter类型的Bean,排除basic后构建列表 @Bean("searches") public List<Parameter> getSearch(List<Parameter> allParameters) { return allParameters.stream() .filter(param -> !"basic".equals(param.getName())) // 根据实际标识排除模板Bean .collect(Collectors.toUnmodifiableList()); } }
三、是否需要用BeanFactory获取Bean?
不需要。Spring的依赖注入机制已经能完美处理这种场景,直接注入Bean或自动收集同类型Bean的方式更简洁、符合Spring最佳实践。只有在动态获取Bean(比如根据运行时参数决定获取哪个Bean)或非Spring管理类中获取Bean的特殊场景下,才需要使用BeanFactory或ApplicationContext。
内容的提问来源于stack exchange,提问作者Avinash Mishra
相关产品推荐
相关产品推荐

