我正在尝试在 Spring Boot 中动态注册 Bean,但是如果尝试 Autowiring 动态 Bean 之一,Bean 的创建顺序始终会导致 NoSuchBeanDefinitionException
。
我的设置由两个项目组成,一个是 spring-boot-starter 项目,另一个是实际的 spring-boot 应用程序。
实际的应用程序注册一个BeanDefinitionRegistryPostProcessor
来添加bean定义。实例本身是通过启动项目中定义的另一个 bean 构建的,该项目本身将另一个 bean 作为依赖项。
为了使用动态注册的 bean,我创建了一个用 @Component
注释的类,并定义了一个构造函数,期望所述 bean 作为参数。
当我通过设置 @Autowired(required=false) 来调试应用程序时,我可以看到组件的构造函数在创建动态 bean 之前被调用。而且,当时连工厂bean都还没有创建。
将带有工厂 bean 名称的 @DependsOn
添加到组件中,导致首先创建工厂,而不是动态 bean。
使用动态 bean 的名称设置 @DependsOn
是可行的,但这似乎不是解决此问题的正确方法。
为什么 Spring 以错误的顺序创建我的 bean,我该如何解决这个问题?
编辑:
我能够在示例存储库中重现该问题:
https://github.com/maveeee/spring-dynamic-bean-demo/
最佳答案
您可以使用@Order
定义带注释的组件或 bean 的排序顺序的注释。
考虑到在 Spring 4.0 之前,此注释仅用于 AspectJ 执行顺序。 Spring 4.0之后,支持将注入(inject)的组件排序到集合中。因此,Spring 将根据它们的顺序值注入(inject)相同类型的 Autowiring bean。
例如:
interface IBean {
String getName();
}
public class BeanX implements IBean {
public BeanX() {}
@Override
public String getName() {
return "BeanX";
}
}
public class BeanY implements IBean {
public BeanY() {}
@Override
public String getName() {
return "BeanY";
}
}
@Component
public class RandomComponent {
@Autowired
private List<IBean> beans;
@PostConstruct
public void getBeanValues() {
System.out.println("\n---@Bean---\n");
for (IBean b : beans) {
System.out.println(b.getName());
}
}
@Bean
@Order(1)
public IBean getBeanX() {
return new BeanX();
}
@Bean
@Order(0)
public IBean getBeanY() {
return new BeanY();
}
}
将打印:
---@Bean---
BeanY
BeanX
因为 BeanY
的优先级(0
,较低的值)高于 BeanX
(较高的值,1
) .
相关文章:
关于java - Spring Boot Factory Bean 创建顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53072663/