java - Spring Boot Factory Bean 创建顺序

标签 java spring spring-boot spring-boot-starter

我正在尝试在 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) .

GitHub Demo

相关文章:

关于java - Spring Boot Factory Bean 创建顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53072663/

相关文章:

java.io.FileNotFoundException : class path resource [WEB-INF/classes/library. 属性]无法打开,因为它不存在

eclipse - 从 eclipse+gradle 运行时,Spring Boot 错误地加载了测试配置

java - Autowire 不适用于 Spring Boot 中的自定义 UserDetailsS​​ervice

java - java中的算术平均值

java - 如何在 Talend 中处理错误和异常

java - 具有反向代理的 Spring SAML - 响应的响应字段与发送的消息不对应

java - Spring:NotWritablePropertyException

java - AJAX JSON 数据检索(Portlet+Liferay+JSON+Spring)

java - 使用带有 Springs 的外部属性文件作为 init.d 服务

java - 编程模式 - 示例研究