繁体   English   中英

使用Spring在Tomcat启动期间委派处理

[英]Delegate processing during Tomcat startup with Spring

我已经定义了一个bean,它需要在@PostConstruct生命周期阶段(启动期间)进行一些繁重的处理。

按照目前的情况,我会在处理循环的每次迭代中向执行程序服务提交一个新的Callable。 我在成员变量中保留了从这些提交中返回的Future对象的列表。

@Component
@Scope("singleton")
public class StartupManager implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ExecutorService executorService;

    private final Map<Class<?>, Optional<Action>> actionMappings = new ConcurrentHashMap<>();
    private final List<Future> processingTasks = Collections.synchronizedList(new ArrayList<>());

    @PostConstruct
    public void init() throws ExecutionException, InterruptedException {

        this.controllers.getHandlerMethods().entrySet().stream().forEach(handlerItem -> {

            processingTasks.add(executorService.submit(() -> {

                // processing

            }));

        });

    }

}

这个bean实现了ApplicationListener接口,因此它可以侦听ContextRefreshedEvent,它允许我检测应用程序何时完成启动。 我使用这个处理程序循环遍历Futures列表并调用阻塞get方法,该方法确保在应用程序继续之前已经发生了所有处理。

@Override
public void onApplicationEvent(ContextRefreshedEvent  applicationEvent) {
    for(Future task : this.processingTasks) {
        try {
            task.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new IllegalStateException(e.getMessage());
        }
    }
}

我的第一个问题是:将actionMapping流更改为parallelStream是否会实现与向执行程序服务提交任务相同的功能? 有没有办法可以将现有的执行程序服务传递到并行流中,以便使用我为bean定义的线程池大小?

其次..作为处理的一部分..读取actionMappings地图并将条目放入其中。 这足以使这个Map成为ConcurrentHashMap以使其在这种情况下的线程安全吗?

其次是实现ApplicationListener接口并监听ContextRefreshedEvent是检测应用程序何时启动的最佳方法,因此通过阻止来强制完成未处理的任务? 或者这可以用另一种方式完成吗?

谢谢。

  1. 关于使用parallelStream() :不,这正是使用此方法的主要缺点。 它应该仅在线程池大小无关紧要时使用,因此我认为基于ExecutorService的方法很好。

    由于您使用的是Java 8,因此您也可以使用CompletableFuture.supplyAsync()方法,该方法具有Executor的重载。 由于ExecutorService扩展了Executor ,你可以将它传递给你的ExecutorService ,你就完成了!

  2. 我认为ConcurrentHashMap很好。 它确保所有操作中的线程安全,特别是在需要添加或修改条目时。

  3. 什么是ContextRefreshedEvent被触发? 根据Javadoc:

    ApplicationContext初始化或刷新时引发的事件。

    这并不能保证你的onApplicationEvent()方法只被调用一次,也就是说,当你的bean被正确初始化时,包括执行@PostConstruct -annotated方法。

    我建议你实现BeanPostProcessor接口,并将你的Future -checkup逻辑放在postProcessAfterInitialization()方法中。 两个BeanPostProcessor方法分别在InitializingBean.afterPropertiesSet()方法(如果存在)之前和之后调用。

我希望这会有所帮助......

干杯,

杰夫

暂无
暂无

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

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