@PostConstruct 的执行顺序

Execution Order of @PostConstruct

我的 JEE 应用程序中有 2 个单例,我想在启动时对其进行初始化。像这样:

@Singleton
@Startup
public class ServiceB {

    @EJB
    private ServiceA a;

    @PostConstruct
    private void init() {
        ....
    }
}

ServiceB 并不真正需要 ServiceA,我只是添加了依赖项以确保 ServiceA 在 ServiceB 的 init() 方法开始之前完全初始化(阅读:@PostConstruct-method finished)。

但它不会等待。 ServiceB 实际上在ServiceA 之前启动。

有没有办法确保一个 Bean 的 @PostConstruct- 方法等待另一个 Bean 的 @PostConstruct-method 完成?

我知道我可以删除 ServiceA 中的 @PostConstruct 注解并直接从 ServiceB 中调用它

    @PostConstruct init() {
        a.init();
    }

但我有没有 ServiceB 的部署。所以我不能依赖 ServiceB 来初始化 ServiceA。 ServiceA 必须自己做。并且 ServiceB 必须等待 ServiceA 完成它。

使用 @DependsOn 注释声明对启动 bean 的初始化依赖性。

示例:

@Singleton
@Startup
public class ServiceA {
    @PostConstruct
    public void init() { ... }
}

@Singleton
@Startup
@DependsOn("ServiceA")
public class ServiceB {
    @EJB
    ServiceA a;

    @PostConstruct
    public void init() { ... } // will be called after a is initialized
}

关于@DmiN给出的答案的问题 (我是新用户,所以无法 post 直接发表评论)

根据您的建议(如下代码所示)-- 我同意服务B 将在服务A 初始化后启动(只是初始化,而不是post构造完成)。但是我怀疑是否可以保证ServiceB的init方法永远不会运行除非ServiceA的PostConstruct方法已经执行完毕?正确吗?

@Singleton
@Startup
public class ServiceA {
    @PostConstruct
    public void init() { ... }
}

@Singleton
@Startup
@DependsOn("ServiceA")
public class ServiceB {
    @EJB
    ServiceA a;

    @PostConstruct
    public void init() { ... } // will be called after a is initialized
}

@PostConstruct注解用于依赖注入完成后执行的方法,所以到这里服务A在服务B中的注入就完成了,然后就可以执行服务B的init函数了

public class ServiceA {

@PostConstruct
public void init() { }

}


public class ServiceB {

@Autowired
ServiceA a;

@PostConstruct
public void init() { }
}

作为一种简单的替代解决方案,您可以在一个地方手动收集所有应按定义顺序初始化的独立 bean。它有助于避免 @DependsOn

public interface OrderedPostConstruct {
    void init();
}

// ==== Production ====
@Configuration
public class InitConfig {

    private final ObjectProvider<OrderedPostConstruct> initializers;

    @PostConstruct
    public void initEntryPoint() {
        initializers.orderedStream().forEach(Initialize::init);
    }
}

@Order(1)
@Component
public class OneUsefullComponent implements OrderedPostConstruct {
    @Override
    public void init() {
        // executed first
    }
}

@Order(2)
@Component
public class TwoUsefullComponent implements OrderedPostConstruct {
    @Override
    public void init() {
        // executed second
    }
}

// ==== Integration tests ====
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
public class TestDataPopulator implements OrderedPostConstruct {
    @Override
    public void init() {
        // populate data for tests
    }
}