简体   繁体   English

@PostConstruct 的执行顺序

[英]Execution Order of @PostConstruct

I have 2 singletons in my JEE application that I want to initialize at start up.我的 JEE 应用程序中有 2 个单例,我想在启动时对其进行初始化。 Something like this:像这样的东西:

@Singleton
@Startup
public class ServiceB {

    @EJB
    private ServiceA a;

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

ServiceB doesn't really need ServiceA, I just added the dependency to make sure that ServiceA is fully initialized (read: @PostConstruct-method finished) before ServiceB's init() -Method starts. ServiceB 并不真正需要 ServiceA,我只是添加了依赖项以确保在 ServiceB 的 init() 方法启动之前完全初始化 ServiceA(阅读:@PostConstruct-method finished)。

But it doesn't wait.但它不会等待。 ServiceB actually starts before ServiceA. ServiceB 实际上在 ServiceA 之前启动。

Is there any way to ensure that one Bean's @PostConstruct- method waits for another Bean's @PostConstruct-method to finish?有没有办法确保一个 Bean 的 @PostConstruct- 方法等待另一个 Bean 的 @PostConstruct- 方法完成?

I know I could just remove the @PostConstruct Annotation in ServiceA and call it directly from ServiceB我知道我可以删除 ServiceA 中的 @PostConstruct 注释并直接从 ServiceB 调用它

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

but I have deployments where there is no ServiceB.但我有没有 ServiceB 的部署。 So I can't rely on ServiceB to init ServiceA.所以我不能依赖ServiceB来初始化ServiceA。 ServiceA has to do that itself. ServiceA 必须自己做。 And ServiceB must wait for ServiceA to be done with it. ServiceB 必须等待 ServiceA 完成它。

Use the @DependsOn annotation to declare an initialization dependency on startup beans.使用@DependsOn注释声明对启动 bean 的初始化依赖。

Example:例子:

@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
}

A question on the answer given by @DmiN (I am new user so not able to post a comment directly)关于@DmiN给出的答案的问题(我是新用户,所以无法直接发表评论)

With your suggestion (as shown in code below) -- I agree that Service B will start after Service A is initialized (just initialized, not that postconstruct is complete).根据您的建议(如下面的代码所示)——我同意服务 B 将在服务 A 初始化后启动(只是初始化,而不是 postconstruct 完成)。 But I doubt if it can be guaranteed that ServiceB's init method will never run unless the Service A's PostConstruct method has finished execution?但是我怀疑是否可以保证ServiceB的init方法永远不会运行,除非Service A的PostConstruct方法完成执行? Correct?正确的?

@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
}

The @PostConstruct annotation is used for methods executed after dependency injection is complete, So here the injection of service A in service B is done, then the init function of Service B can be executed @PostConstruct注解用于依赖注入完成后执行的方法,所以这里服务A在服务B中的注入完成了,那么就可以执行服务B的init函数了

public class ServiceA {

@PostConstruct
public void init() { }

}


public class ServiceB {

@Autowired
ServiceA a;

@PostConstruct
public void init() { }
}

As a simple alternative solution, you can manually collect all your independent beans that should be inited in a defined order in one place.作为一种简单的替代解决方案,您可以在一个地方手动收集所有应按定义顺序启动的独立 bean。 It helps to avoid @DependsOn它有助于避免@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
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM