Smartproxy is a library to dynamically create proxy classes and
instances. This is similar to the
java.lang.reflect.Proxy class but
instead of forwarding the calls to an invocation handler, the
smartproxy package use an underlying object to provide the
default behavior and an abstract class to override some methods. The
smartproxy approach, while less versatile than the jlrP one has a
couple of advantages:
Suppose you want to proxify objects implementing the interface
Underlying. You'll have to create an abstract
Implementor class which will implement
Underlying which will define the methods you want to
override. The Implementor is also responsible for
the storage of a reference to the underlying object and should
also implement the ProxifiedObject interface in
order to provide the getUnderlying method.
The smartproxy will create a proxy class extending
ProxifiedObject and implementing
Underlying. This class will implement the methods
from Underlying underlying missing from
the implementor as:
return method(parameters)
{
return ((Underlying)getUnderlying()).method(parameters);
}
So the smartproxy package actually creates a simple class forwarding to the underlying object the methods not in the implementor class. This could be done be automatically write the Java code, use javac to create the associated bytecode and then load it into the JVM. However this is quite unpractical since it requires a JDK instead of a JRE and may require to write temporary files (I didn't investigate much but I'm not sure that the javac API can work from memory directly). Furthermore I guess that the compilation process will be a big resource consumer. So instead of creating Java code, the smartproxy library directly writes bytecode to define the proxy classes or to be more accurate, uses the BCEL Library to perform this task.
Before the links a little warning:
This is alpha software and it may run, not run, crash your computer, etc. Beside as an alpha software the API may change between subsequent releases.
Binary and source archive can be found here in both tar.gz or zip format. The BCEL library is mandatory to use smartproxy but version 5.1 is included for convenience in both source and binary distributions.
If you downloaded the binary distribution you can skip to the next point.
The source distribution provides an
ant build file. I use the
jikes
compiler instead of javac so if you don't have it you can either
download it or comment out the three lines in the
build.xml file:
<!-- Use jikes compiler, if you don't have it comment out the next lines -->
<property name="build.compiler.emacs" value="true"/>
<property name="build.compiler.pedantic" value="true"/>
<property name="build.compiler" value="jikes"/>
The default
target will build the smartproxy.jar and smartproxy-src.zip (To
use with Eclipse as source
for the jar). Other targets can be seen with ant
-projecthelp.
If you want to be able to run the JUnit tests you'll have to
copy get JUnit and copy the
junit.jar file into the lib
directory.
Untar/unzip the distribution archive and manage to get the
bcel-5.1.jar and smartproxy.jar from
the lib directory in the classpath, et
voilą. The bcel-5.1.src.zip is provided as a convenience
for Eclipse users but it may be useful with other IDEs. The use
of the provided bcel jar is not mandatory but so far smartproxy
had only been test with release 5.1 and won't probably work with
earlier releases.
In this example, we assumed that you wanted to proxify objects
implementing the SimpleInterface interface. This
interface defines four methods called, a, b, c and d with
various parameters. You
first need to write an implementor class implementing
SimpleInterface, ProxifiedObject and
taking care of storing the underlying object:
public abstract class SimpleImplementor implements SimpleInterface, ProxifiedObject
{
private SimpleInterface underlying;
public SimpleImplementor(SimpleInterface underlying)
{
this.underlying = underlying;
}
public int a()
{
return 10000;
}
public String d(String x)
{
return "not" + x;
}
public Object getUnderlying()
{
return underlying;
}
}
You can now create proxy using the following snippet:
// Create the proxy factory for the set on interface/implementor.
ProxyFactory factory = ProxyFactory.getInstance(SimpleImplementor.class, SimpleInterface.class);
// Creates an underlying object.
SimpleInterface base = new SimpleBaseClass();
// Proxify the underlying object.
SimpleInterface proxified = (SimpleInterface) factory.createProxy(new Object[] { base });
The Javadoc API documentation is available in the distributions and online. Both binary and source distribution includes the source code for the JUnit tests and a few examples.
Smartproxy is distributed under the term of the BSD License and it used the BCEL Library developed by the Apache Software Foundation which is released under the terms of the Apache License.
Don't hesitate to contact me for anything relative to smartproxy (bug, suggestion, etc.).