// Demo of hard-code and reflective proxies. // In some places I have put a comment to // indicate classes that would logically be public // if I used more than one file import java.lang.reflect.*; /* public */ interface Foo { void setValue( int x ); int getValue( ); } /* public */ class FooFactory { public static Foo allocateFoo( ) { Foo f = new FooImpl( ); // This is the call using old-style write your own // return new FooProxy( f ); // Here is the call using Java 1.3 dynamic proxies return (Foo) Proxy.newProxyInstance( Foo.class.getClassLoader( ), new Class[] { Foo.class }, new FooHandler( f ) ); // Here is what the Java 1.3 is actually doing for you // return new GeneratedProxy( new FooHandler( f ) ); } private FooFactory( ) { } // No FooFactory objects } class TestProxy { public static void main( String[] args ) { Foo f = FooFactory.allocateFoo( ); f.setValue( 37 ); System.out.println( "Foo value is " + f.getValue( ) ); } } /* package visible */ class FooImpl implements Foo { public void setValue( int x ) { value = x; } public int getValue( ) { return value; } private int value; } /* package visible */ class FooProxy implements Foo { public FooProxy( Foo d ) { delegate = d; } public void setValue( int x ) { System.out.println( "Invoking setValue via hard coded proxy" ); delegate.setValue( x ); } public int getValue( ) { System.out.println( "Invoking getValue via hard coded proxy" ); return delegate.getValue( ); } private Foo delegate; } /* package visible */ class FooHandler implements InvocationHandler { public FooHandler( Object d ) { delegate = d; } public Object invoke( Object proxy, Method meth, Object[] args ) throws Throwable { System.out.println("Invoking " + meth.getName( ) + " via reflective proxy" ); return meth.invoke( delegate, args ); } private Object delegate; } // Some stuff commented out because Proxy.getInvocation handler // will notice that what is here is a phony proxy. // Commented out code is what really gets generated /* public */ final class GeneratedProxy extends Proxy implements Foo { public GeneratedProxy( InvocationHandler h ) { super( h ); handler = super.h; } public void setValue( int x ) { Object ret = null; try { Method m = myClass.getMethod( "setValue", new Class[] { Integer.TYPE } ); ret = handler.invoke( this, m, new Object[] { new Integer( x ) } ); } catch( Throwable e ) { if( e instanceof RuntimeException ) throw (RuntimeException) e; if( e instanceof Error ) throw (Error) e; } } public int getValue( ) { Object ret = null; try { Method m = myClass.getMethod( "getValue", new Class[] { } ); ret = handler.invoke( this, m, new Object[] { } ); } catch( Throwable e ) { if( e instanceof RuntimeException ) throw (RuntimeException) e; if( e instanceof Error ) throw (Error) e; } return ((Integer)ret).intValue( ); } private InvocationHandler handler; private static final Class myClass = Foo.class; }