This post originated from an RSS feed registered with Java Buzz
by Brian McCallister.
Original Post: Inverting the Inversion of Control
Feed Title: Waste of Time
Feed URL: http://kasparov.skife.org/blog/index.rss
Feed Description: A simple waste of time and weblog experiment
So I was brainstorming with Robert over lunch today and realized we can invert the inversion of control, to get even more flexibility and power. You might think that doing this means "just new-ing anything you need" but that isn't quite it. The key thing to see is that "new" *is* really useful from a programmer's perspective, if annoying from a sysadmin or deployer's perspective.
A new operation really means "I need something which behaves according to the protocols defined by this thing, and which doesn't have any state anything else is touching." Long ago we gave up caring if it is actually a Foo as Foo is simply an abstraction for a byte array, which in the JVM is just a bunch of Strings anyway, when you get down to it.
So we need a compile step, or a runtime bytecode weaving step. Aspectwerkz does this nicely. We use that to intercept calls to "new" and generate a runtime subclass of the thing being newed. At the same time we use JAD to decompile it, and shove the contents of all methods into strings.
The runtime subclass acts as a proxy (CGLIB has code to do this now, works nicely) to call out to a table lookup for the thing to invoke (maybe store index into table in the generated proxy for performance). The table is really just an interface like:
The default implementation would just recompile the JAD'd source in a more convenient form (convert to static taking "self" as first arg), and invoke away. So far, however, we have no advantage over the normal compiled Java.
But ah-hah! We do, we can use a different implementation of FunctionTable which stores the method body as a String in Derby and uses BeanShell (or Janino!) to invoke it. So a method invocation is completely configurable at runtime! Not deploy time, runtime.
If you find a bug, you can fix it without a redeploy:
update
methods
set
method_body='return new Integer(42);'
where
package = 'org.example.foo' and
name = 'getDayOfWeek';
Aspect Oriented Inversion of Control with Blocks! (and no XML!)