[英]Java service with async method invocation
给定一个FooService
与read
和write
由支持操作repository
,我想提供它的一个变种异步的使用Spring
REST Web服务(可能使用Akka
因为它已经对其他问题的候选人...)。
到目前为止,我有冗长且有些笨拙的变体
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
}
实现对该服务的异步操作还有哪些其他好的变体?
为了限制范围,我们不要直接考虑Proxies
本身,因为它们本身并不提供解决方案。
由于涉及到一些Spring,因此我将仅使用AOP建议来自动化您的“笨拙”方法。 咨询班:
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();
}
});
}
}
并在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>
这是一个非常轻巧的解决方案。 无论如何,您的最后一段让我觉得您想要一个更自动化的解决方案。
首先,我认为您的代码中有错别字-您是在run()创建无限循环中调用相同的writeSomeThing()方法吗?
除此之外,我认为这几乎就是您将如何使用Executors在纯Java中做到这一点。 当然可以说得更详细些,但是您可以将此代码移到同步实现的代理/拦截器中,这会将任务提交给执行者并将控制权返回给调用者,因此使同步实现摆脱了这种非功能性逻辑。 然后,您可以直接调用同步实现以获取同步行为,也可以调用代理以获取异步,或者根据参数等对代理进行冷处理。
如果您希望减少代码编写工作并具有足够的灵活性,那么肯定有可用的选项-您已经提到过,除了Akka之外,您还可以查看Apache Camel的SEDA队列或任何轻量级消息传递解决方案,这些解决方案都可以使您将任务发布到工作队列中用于在主线程之外进行处理。
您可以使用方法列表和class.invoke构建单个函数。
如果是一次性的,则Eclipse提供按模板的代码生成,或者甚至更好的是,您可以编写Java代码来读取函数列表并为您生成包装器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.