Java:在运行时创建类型的新实现?

时间:2009-10-20 19:23:45

标签: java code-generation interface wrapping

所以,我意识到答案可能是“很难”,但是:

我有一个奇怪的想法,并想知道在Java中是否可以创建一个类似的方法:

<T> T wrapInterface (Class<T> interfaceClass, T wrappedObject) {
  if (mClass.isInterface()) {
    //create a new implementation of interfaceClass that, in each method, 
    //does some action before delegating to wrappedObject
    return thatImplementation;
  }
}

所以基本上,如果我的接口Foo定义了一个方法foo(),我希望这个方法创建一个看起来像这样的新类,用wrappedObject作为构造函数参数创建该类的实例,然后返回它:

public class GeneratedClass implements Foo {
  private Foo wrapped;
  public GeneratedClass (Foo wrapped) {
    this.wrapped = wrapped;
  }
  @Override
  public void foo () {
    System.out.println("Calling Foo.foo() on wrapped object " + 
                        wrapped.toString());
    wrapped.foo();
  }
}

我正在考虑的应用程序比仅记录调用更复杂,但是日志记录足以满足这个想法。我想用大量的接口类型来做这个,这就是我不想手工编写所有GeneratedClasses的原因。

不需要语言外特征的解决方案的奖励积分(引入AspectJ或其他类似的东西),如果仅使用标准JDK库就可以获得双倍奖励积分。

(我不需要一个精确的,可编译的答案;只需指向正确的工具/库/等等,这些就可以让我这样做。)

谢谢!

2 个答案:

答案 0 :(得分:3)

这是一个非常简单的实现(对于你想要做的事情来说不够好,但有一些调整......主要的看法是类加载器问题,然后可能会有一些验证问题,等等。我将代码用于测试目的,因此它不完全是生产质量的东西。

    @SuppressWarnings("unchecked")
    public static <T> T generateProxy(Object realObject, Class<?>... interfaces) {
        return (T) Proxy.newProxyInstance(realObject.getClass().getClassLoader(), interfaces, new SimpleInvocationHandler(realObject));
    }


    private static class SimpleInvocationHandler implements InvocationHandler {
        private Object invokee;

        public SimpleInvocationHandler(Object invokee) {
            this.invokee = invokee;
        }

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            method = invokee.getClass().getMethod(method.getName(), method.getParameterTypes());
            if (!method.isAccessible()) {
                method.setAccessible(true);
            }
            try {
                return method.invoke(invokee, args);
            } catch (InvocationTargetException e) {
                throw e.getTargetException();
            }
        }
    }

答案 1 :(得分:1)

您需要的是ASM

来自asm-guide.pdf
2.2.3生成课程
生成类的唯一必需组件是ClassWriter组件。 我们举一个例子来说明这一点。请考虑以下界面:

package pkg;
public interface Comparable extends Mesurable {
  int LESS = -1;
  int EQUAL = 0;
  int GREATER = 1;
  int compareTo(Object o);
}

可以通过对ClassVisitor的六次方法调用生成它:

ClassWriter cw = new ClassWriter(0);
cw.visit(V1_5, ACC_PUBLIC + ACC_ABSTRACT + ACC_INTERFACE,
    "pkg/Comparable", null, "java/lang/Object",
    new String[] { "pkg/Mesurable" });
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "LESS", "I",
    null, new Integer(-1)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "EQUAL", "I",
    null, new Integer(0)).visitEnd();
cw.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "GREATER", "I",
    null, new Integer(1)).visitEnd();
cw.visitMethod(ACC_PUBLIC + ACC_ABSTRACT, "compareTo",
    "(Ljava/lang/Object;)I", null, null).visitEnd();
cw.visitEnd();
byte[] b = cw.toByteArray();