通过reflection / javassist调用不存在的函数

时间:2015-03-09 17:29:06

标签: java reflection javassist

我需要调用一个函数 - (属性的getter和setter),但我的问题是,属性的​​名称是在运行时生成的(某个变量的名称+数字)。

是否可以通过javassist或gclib操作字节码,以便将函数调用定向到某个代理对象/函数,并且有真实的方法名称和从被调用函数名称中提取的数字,以便我可以调用之后的功能(以数字作为参数)?

我尝试了以下内容,但它没有用:

MethodHandler handler = new MethodHandler() {
        @Override
        public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) {
             String realMethodName=thisMethod.substring(0,5);
             Integer param=Integer.parseInt(thisMethod.substring(5));
            Method m = self.getClass().getMethod(realMethodName);
            m.invoke(self,param);
            return null;
        }
    };

2 个答案:

答案 0 :(得分:1)

我认为这可能是使用Java反射代理对象的少数情况之一可能派上用场。

你可以定义一些接口,但是将方法委托给(动态)调用处理程序,然后调用那些" getter / setter"方法

附注:在实现这样的调用处理程序时,您必须了解对相应对象的ANY方法调用将触发其调用"方法;调用toString或equals或从Object继承的其他任何事件时的事件。

编辑:还有一个(不同的)想法:你确定你需要创建动态方法名吗?如果您有一些数字(或基于字符串)键 - 例如没有使用Map?

    Map<WhateverKeyType,YourPropertyClass> 

这将是更多&#34;正常的Java&#34;处理问题的方法(而不是考虑反射或字节码操作)。

答案 1 :(得分:0)

如果你想实现类似的东西,但想到使用另一个库而不是javassist,请考虑using Byte Buddy(我写的,为了披露)。

考虑到,你有一个界面

interface Foo { Object getProperty() }

您希望实现访问bean的属性

class Bar { Object getAbc123() { ... } }

然后使用Byte Buddy,你可以实现一个类

Foo accessor = new ByteBuddy()
  .subclass(Foo.class)
  .method(named("getProperty"))
  .intercept(MethodCall.invoke(Bar.class.getDeclaredMethod("getAbc123"))
                        .on(new Bar()))
  .make()
  .load(Foo.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
  .getLoaded()
  .newInstance();
接口的

getProperty的调用重定向到您选择的方法。通过一些自定义,您肯定可以创建更通用的解决方案。