在 @PostConstruct 函数中的反应式调用

huangapple go评论77阅读模式
英文:

Reactive calls in @PostConstruct function

问题

可以有人帮我完成以下操作:

@PostContruct public void func() {
   webclient.get()...subscribe();
}

在 func() 方法返回后,webclient 调用将会终止。很可能会在第一个请求到达之前发生,但不能保证。另一种选择是使用 block(),但这会违反响应式的目的。

在 @PostConstruct 方法中进行响应式调用的正确方法是什么呢?

谢谢。

英文:

Could somebody help me to do the following:

@PostContruct public void func() {
   webclient.get()...subscribe();
}

webclient call will terminate after func() returns. Most likely it will happen before the first request comes in, but no guarantees. The other option is to block(), which defeats the purpose of being reactive.

What would be the right way to make reactive calls in @PostConstruct methods?

Thank you.

答案1

得分: 1

我创建了一个简单的 bean。

同步更新:

@Component
public class BeanTest {

    private String postConstructValue;

    @PostConstruct
    public void init(){
        try {
            Thread.sleep(5000);
            this.postConstructValue = "Construction done";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(fixedRate = 500)
    public void print(){
        System.out.println(
                this.postConstructValue
        );
    }

}

应用启动花费了一些时间(超过5秒),因为我们在 post construct 中模拟了一些耗时的过程。Scheduled 打印方法仅在应用启动后才开始打印。它开始打印“Construction done”消息。

异步更新:

@Component
public class BeanTest {

    private String postConstructValue;

    @PostConstruct
    public void init(){
        Flux.just("Construction done")
                .delayElements(Duration.ofSeconds(5))
                .subscribe(s -> this.postConstructValue = s);
    }

    @Scheduled(fixedRate = 500)
    public void print(){
        System.out.println(
                this.postConstructValue
        );
    }

}

在这种方法中,应用在2秒内启动。打印方法开始打印null几秒钟。然后它开始打印“Construction done”。它不会终止 Flux postConstruct 值的更新。这是异步发生的。

当您想要非阻塞行为并异步完成某些任务时,反应式方法是很好的选择。如果您认为组件的创建应该等待适当的构造,则必须进行阻塞!否则,您可以选择第二种方法。

英文:

I created a simple bean.

Synchronous update:

@Component
public class BeanTest {

    private String postConstructValue;

    @PostConstruct
    public void init(){
        try {
            Thread.sleep(5000);
            this.postConstructValue = "Construction done";
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Scheduled(fixedRate = 500)
    public void print(){
        System.out.println(
                this.postConstructValue
        );
    }

}
  • It took some time for app to start (more than 5 seconds) because we simulated some time consuming process in the post construct. Scheduled print method started printing only after the app started. It started printing "Construction done" message.

Asynchronous update:

@Component
public class BeanTest {

    private String postConstructValue;

    @PostConstruct
    public void init(){
        Flux.just("Construction done")
                .delayElements(Duration.ofSeconds(5))
                .subscribe(s -> this.postConstructValue = s);
    }

    @Scheduled(fixedRate = 500)
    public void print(){
        System.out.println(
                this.postConstructValue
        );
    }

}
  • Now in this approach, the app started within 2 seconds. Print method starting printing null for few seconds. Then it started printing "Construction done". It does not terminate the Flux postConstruct value update. It happened asynchronously.

Reactive approach is good when you want a non-blocking behavior and getting something done asynchronously. If you think that your component creation should wait for proper construction, you have to block! Otherwise, you can go with second approach.

答案2

得分: 0

你可以使用toFuture来使用标准的Java异步机制:

@PostConstruct
public void postConstruct() throws ExecutionException, InterruptedException {
    log.info("开始 postConstruct");
    WebClient webClient = WebClient.create();
    webClient.get().uri(...).retrieve()
        .toEntity(String.class)
        .flatMap((responseEntity) -> {
            log.info("数据已检索。");
            return Mono.just(true);
         })
         .toFuture()
         .get();
    log.info("设置完成");
}

日志中会得到以下输出:

开始 postConstruct
数据已检索。
设置完成

按照这个顺序...

英文:

You can use toFuture to use the standard Java async mechanisms:

@PostConstruct
public void postConstruct() throws ExecutionException, InterruptedException {
    log.info("Start postConstruct");
    WebClient webClient = WebClient.create();
    webClient.get().uri(...).retrieve()
        .toEntity(String.class)
        .flatMap((responseEntity) -> {
            log.info("Data retrieved.");
            return Mono.just(true);
         })
         .toFuture()
         .get();
    log.info("Setup complete");
}

And you'll get in the logs:

Start postConstruct
Data retrieved
Setup complete

In that order ...

huangapple
  • 本文由 发表于 2020年4月5日 06:24:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/61035588.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定