Search code examples
javaeasymockproxy-classes

creating Java Proxy instance for a class type?


I have the following code that works for creating a Proxy instance for an interface type backed by an InvocationHandler implementation, however when I use a concrete class type it doesn't work and this is well known and documented in Proxy.newProxyInstance:

    // NOTE: does not work because SomeConcreteClass is not an interface type
    final ClassLoader myClassLoader = SomeConcreteClass.getClassLoader();
    SomeConcreteClass myProxy = (SomeConcreteClass) Proxy.newProxyInstance(myClassLoader, new Class[] {
        SomeConcreteClass.class }, new InvocationHandler() { /* TODO */ });        

However, if I recall correctly I have seen this use-case work in some mock frameworks where it is possible to mock a concrete class type e.g. EasyMock. Before checking up their source code can anyone indicate what needs to be done to proxy also concrete class types and not only interfaces?


Solution

  • JDK dynamic proxies only work with interfaces. If you want to create a proxy with a concrete superclass you need to use something like CGLIB instead.

    Enhancer e = new Enhancer();
    e.setClassLoader(myClassLoader);
    e.setSuperclass(SomeConcreteClass.class);
    e.setCallback(new MethodInterceptor() {
      public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        return proxy.invokeSuper(obj, args);
      }
    });
    // create proxy using SomeConcreteClass() no-arg constructor
    SomeConcreteClass myProxy = (SomeConcreteClass)e.create();
    // create proxy using SomeConcreteClass(String) constructor
    SomeConcreteClass myProxy2 = (SomeConcreteClass)e.create(
        new Class<?>[] {String.class},
        new Object[] { "hello" });