0

给定由 a 支持的FooServicewithreadwrite操作repository,我想提供它的异步变体以在SpringREST 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,因为它们本身并没有提供解决方案。

4

3 回答 3

2

由于涉及到一些 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>

这是一个非常轻量级的解决方案。无论如何,你的最后一段让我觉得你想要一个更自动化的解决方案。

于 2012-11-08T22:43:58.337 回答
1

首先,我认为您的代码中存在拼写错误-您正在从 run() 创建无限循环中调用相同的 writeSomeThing() 方法?

除此之外,我认为这几乎是您将如何在纯 Java 中做到这一点 - 使用 Executors。当然更冗长,但是您可以将此代码移动到代理/拦截器的同步实现中,这会将任务提交给执行程序并将控制权返回给调用者,因此同步实现不会出现这种非功能性逻辑。然后,您可以直接调用同步实现以获取同步行为或调用代理以获取异步,或者根据参数等可能代理冷处理。

如果您想要更少的编码工作并具有足够的灵活性,那么肯定有可用的选项 - 除了您已经提到的 Akka,您可以查看 Apache Camel 的 SEDA 队列或任何可以让您将任务发布到工作队列的轻量级消息传递解决方案用于在主线程之外进行处理。

于 2012-11-08T22:09:59.200 回答
0

您可以使用方法列表和 class.invoke 构建单个函数。

如果是一次性的,Eclipse 通过模板提供代码生成,或者更好的是,您可以编写读取函数列表并为您生成包装器的 java 代码。

于 2012-11-08T22:09:39.340 回答