简体   繁体   English

具有异步方法调用的Java服务

[英]Java service with async method invocation

Given a FooService with read and write operations backed by a repository , I want to provide an asynchronous variant of it to be used in a Spring REST web service (potentially using Akka as it's already a candidate for other problems...). 给定一个FooServicereadwrite由支持操作repository ,我想提供它的一个变种异步的使用Spring REST Web服务(可能使用Akka因为它已经对其他问题的候选人...)。

So far I have the verbose and somewhat clunky variant 到目前为止,我有冗长且有些笨拙的变体

class AsyncFooService extends FooService {

    private final ExecutorService executor = Executors.newCachedThreadPool();
    private final FooService delegate = ...

    @Override
    public void writeSomeThing(Obj o) {
        executor.submit(new Runnable() {
           @Override
           public void run() {
               delegate.writeSomeThing(o);
           }
        });
    }

    // repeat same override & executor semantics for all write* routines
}

What other good variants are there in achieveing asynchronous operations to the service? 实现对该服务的异步操作还有哪些其他好的变体?

To limit the scope, let's not directly consider Proxies as they don't provide a solution in themselves. 为了限制范围,我们不要直接考虑Proxies本身,因为它们本身并不提供解决方案。

As there is some Spring involved I would just use an AOP advice to automate your "clunky" approach a bit. 由于涉及到一些Spring,因此我将仅使用AOP建议来自动化您的“笨拙”方法。 The advice class: 咨询班:

public class AsyncAdvice implements MethodInterceptor {

    @Inject
    private ExecutorService executorService;

    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
        executor.submit(new Runnable() {
            @Override
            public void run() {
                invocation.proceed();
            }
        });
    }
}

and in applicationContext.xml: 并在applicationContext.xml中:

<!-- Synchronous instance -->
<bean id="fooService" class="FooService" scope="singleton">
    <!-- Whatever -->
</bean>

<!-- Asynchronous instance -->
<bean id="asyncFooService" parent="fooService" scope="singleton"/>

<bean id="asyncAdvice" class="AsyncAdvice" scope="singleton">
    <property name="executorService" ref="..."/>
</bean>

<aop:config>
    <aop:advice pointcut="bean(asyncFooService)" and execution=(* FooService.write*(..))"
                advice="asyncAdvice"/>
</aop:config>

This is a pretty lightweight solution. 这是一个非常轻巧的解决方案。 Anyway, your last paragraph makes me think that yoou want a more automated solution. 无论如何,您的最后一段让我觉得您想要一个更自动化的解决方案。

First off I think there is a typo in your code - you're calling the same writeSomeThing() method from within the run() creating infinite loop? 首先,我认为您的代码中有错别字-您是在run()创建无限循环中调用相同的writeSomeThing()方法吗?

Aside from this, I think this is pretty much how would you do it in plain Java - using Executors. 除此之外,我认为这几乎就是您将如何使用Executors在纯Java中做到这一点。 More verbose for sure, but you could move this code to the proxy/interceptor to your sync implementation, which would submit task to executor and return control to the caller, therefore leaving sync implementation free of this non functional logic. 当然可以说得更详细些,但是您可以将此代码移到同步实现的代理/拦截器中,这会将任务提交给执行者并将控制权返回给调用者,因此使同步实现摆脱了这种非功能性逻辑。 Then you could either call sync implementation directly to get sync behavior or call proxy to get async, or perhaps proxy cold handle both depending on the parameters etc. 然后,您可以直接调用同步实现以获取同步行为,也可以调用代理以获取异步,或者根据参数等对代理进行冷处理。

If you want less coding to do and having enough flexibility there are certainly options available - beside Akka, which you already mentioned, you could look at Apache Camel's SEDA queues or to any lightweight messaging solution which would let you to post tasks to the work queues for processing outside of your main thread. 如果您希望减少代码编写工作并具有足够的灵活性,那么肯定有可用的选项-您已经提到过,除了Akka之外,您还可以查看Apache Camel的SEDA队列或任何轻量级消息传递解决方案,这些解决方案都可以使您将任务发布到工作队列中用于在主线程之外进行处理。

You could build a single function using a list of methods and class.invoke. 您可以使用方法列表和class.invoke构建单个函数。

If it is one-off, Eclipse provides code generation by template or,even better, you can write java code which read a list of function and generate the wrappers for you. 如果是一次性的,则Eclipse提供按模板的代码生成,或者甚至更好的是,您可以编写Java代码来读取函数列表并为您生成包装器。

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

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