通过使用动态代理,有没有办法可以返回一个类型与代理接口的方法签名不匹配的对象?

Rya*_*n J 5 java netty

我认为简短的回答可能不是,但我希望我能得到其他建议.假设我有一个数据对象和一个数据服务.数据服务是一个接口,具有以下方法.

public Data getData();
Run Code Online (Sandbox Code Playgroud)

我正在使用以下调用处理程序和Netty为服务创建代理,以执行我称之为异步rpc的操作.代理服务器位于客户端.

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // Convert the call into an async request that returns a ListenableFuture
    APCRequest request = new APCRequest(serviceType, method, args);
    ListenableFuture future = apcClient.asyncMessage(request);

    // This blocks until the future finishes
    return future.get();
}
Run Code Online (Sandbox Code Playgroud)

这很好用.但是,如果我的客户端是UI,我最终将服务调用包装在SwingWorker之类的东西中.我宁愿想出一种方法来返回我已经坐在那里的ListenableFuture.有没有办法在不创建单独的异步服务API的情况下实现这一目标.例如:

public ListenableFuture<Data> getData();
Run Code Online (Sandbox Code Playgroud)

如果我可以让我的InvocationHandler返回错误的类型,我可以使用这样的东西.

public abstract class AsyncServiceCall<S, D> { // S = service type, D = expected doCall return type
    protected final S service;

    protected AsyncServiceCall(Class<S> serviceType, APCClient client) {
        ProxyFactory proxyFactory = new ProxyFactory(client);

        // The true tells the proxyFactory we're expecting a ListenableFuture<D>
        // rather than the real return type.
        service = proxyFactory.createProxy(serviceType, true);
    }

    // Sub-classes would make a normal method call using this.  For
    // example, service.getData()
    public abstract Object doCall();

    @SuppressWarnings("unchecked")
    public ListenableFuture<D> execute() {
        return (ListenableFuture<D>) doCall();
    }
Run Code Online (Sandbox Code Playgroud)

还有另一种方法可以实现我想要的东西吗?性能对我来说不是问题,因此如果没有简单的方法来做我想要的事情,阻塞直到代理可以从未来获得返回值仍然是一个选项.这似乎是浪费,因为我想要在UI中进行异步调用.

保持我的服务API简单优先于任何事情.我希望能够使用简单的服务提供程序进行原型设计,该服务提供程序直接实例化服务实现并插入在开发周期后期使用动态代理/ Netty的远程协议/服务器.

Ian*_*rts 3

如果您想让 API 保持简单,那么我建议在接口中提供异步 API - 将同步实现包装在异步 API 中比反之亦然要容易得多。

public interface DataService {
  public ListenableFuture<Data> getData();
}

public abstract class LocalDataService implements DataService {
  public ListenableFuture<Data> getData() {
    SettableFuture<Data> result = SettableFuture.create();
    try {
      Data theData = computeData();
      result.set(theData);
    } catch(Throwable t) {
      result.setException(e);
    }
    return result;
  }

  protected abstract Data computeData() throws Throwable;
}
Run Code Online (Sandbox Code Playgroud)