2017-09-14 51 views
1

使用反射,可以实现对编译时不可用类的方法的调用。这是使框架代码可以与不同的库版本一起工作的有效方法。如何实现在编译时不可用的接口

现在,假设有一个接口

interface FutureIntf { 
    method1(String s); 
} 

我的代码不知道这个接口,但是我想准备的时间实现,这个接口可以通过未来的库版本可以提供,它需要与这个接口的实现一起工作。我想避免javassist。我认为应该有一种方法使用java.lang.reflect.Proxy.newProxyInstance,但我还没有弄清楚,如何有效地做到这一点。

回答

1

首先您需要以某种方式检索界面。然后像newProxyInstance中提到的那样创建代理。最后,您可以调用接口上的方法或将代理发布到某个服务定位器或类似服务器。

Class<?> unknownInterface = ClassLoader.getSystemClassLoader().loadClass("bar.UnknownInterface"); 

Object proxy = Proxy.newProxyInstance(unknownInterface.getClassLoader(), 
             new Class[] { unknownInterface }, 
             new Handler()); 

unknownInterface.getMethod("someMethod", String.class).invoke(proxy, "hello"); 
// other way to call it: 
// ((UnknownInterface) proxy).someMethod("hello"); 

处理程序类代表要提供实现:

public class Handler implements InvocationHandler { 
    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     if (method.getName().equals("someMethod")) { 
      System.out.println("this is the business logic of `someMethod`"); 
      System.out.println("argument: " + args[0]); 
      return null; 
     } 
     return null; 
    } 
} 

什么是这里的缺点:您需要检索您的接口的Class对象

  • 。可能你需要它的名字。
  • a)您需要知道方法的名称和参数
  • b)或者如果您知道方法的参数类型,您可以按类型匹配它们并忽略名称,例如基于this tutorial about proxies

    args.length == 1 && args[0].getClass == String.class

相关问题