0

withFooServiceread、にwrite裏打ちされた操作を前提として、 REST Webサービスで使用される非同期バリアントrepositoryを提供したいと思います(すでに他の問題の候補であるため、使用する可能性があります...)。SpringAkka

これまでのところ、私は冗長でやや不格好なバリアントを持っています

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を使用して、単一の関数を作成できます。

1回限りの場合、Eclipseはテンプレートによるコード生成を提供します。さらに良いことに、関数のリストを読み取ってラッパーを生成するJavaコードを作成できます。

于 2012-11-08T22:09:39.340 に答える