Dependency Injection with AspectJ and Spring
An anonymous reader writes "IBM DeveloperWorks has an interesting article about the complementary aspects of dependency injection and aspect-oriented programming. Adrian Colyer, Chief scientist of Interface21, examines how to combine these two techniques to 'facilitate advanced dependency injection scenarios.' From the article: 'Dependency injection and aspect-oriented programming (AOP) are two key technologies that help to simplify and purify domain models and application layers in enterprise applications. Dependency injection encapsulates the details of resource and collaborator discovery, and aspects can (among other things) encapsulate the details of middleware service invocations'"
I understand it, but only because I already know this stuff.
A better article to start with is: Inversion of Control Containers and the Dependency Injection pattern, by Martin Fowler. It's older than the one mentioned in the story, but still relevant.
Dependency injection: software is written by decomposing a problem into functionally distinct components. Those components might be self-contained, which makes things easy. In any case, each component fits a particular purpose. If you view that purpose as a contract, the component fulfuls the contract; what you'd like to do is to be able to interchange the implementation of a particular component simply. All you need to know is that a particualr implementation fulfills the demans of the contract for that component. ("Contract" here means the API, or interface, together with the semantics of that interface.)
There are patterns that let you select individual components with late binding - ie, at runtime. "Abstract Factory" is a good google term to look for.
Anyway, some components are not self-contained. They require other components to fulfil their contract. Again, they may not care about the _implementation_ of those components; only that those components exist. Those secondary components might be used solely by the component in question (a "resource") or might collaborate as a peer (a "collaborator"). In either case, the question you face is: this block of code requires a "Foo": how do I get an implementation of "Foo" into it?
That summarises the problem that Dependency Injection attempts to solve. The clue is in the name: the creation of required components is handled by an external framework (the components themselves are not responsible for the creation of their resources or collaborators): hence the phrase, "Inversion of Control" to describe this approach.
The article discusses the use of AOP to manage dependency injection: it's an IoC framework expressed using AOP constructs.
Take the example given. He defines an API for communications between the application and something that looks up movies for a given director, which he calls the finder.
In Java, he needs to instantiate a particular concrete class to provide the finder service. Because of Java's insistence on compile-time type safety, this presents a problem. He wants to be able to plug in a ColonDelimitedMovieFinder class as his finder initially, but still allow someone else to plug in a SQLMovieFinder or whatever without modifying the MovieLister class. So, he has to build a special bit of code to inject a chosen implementation--his PicoContainer with its registerComponentImplementation thing.
In Ruby, you can instantiate any object you like as the finder, because all that matters is that it understands the API messages when it gets them at run time. All you need to do is have a setter method in the original MovieLister object that accepts an object to use as the finder; and you can define that in 1 line of code. Then the MovieLister just uses the object it was passed as the finder. The user of the MovieLister library can then plug in any implementation he likes; he can even change implementation while the application is running. No injectors, no containers, no fancy component libraries needed.
In fact, here is a complete implementation in Ruby, with an example of calling it. (Indentation stripped courtesy of Slashdot, so run it through vim or something.) Note how I simply use a CSV parser object as my Finder, because MovieLister just needs the finder to have the standard Enumerable interface for returning each movie and director in the list.
Again, no special libraries or frameworks were required. Only CSV, and that's in the standard library.
GCHQ Quantum Insert installed. If only our tongues were made of glass, how much more careful we would be when we speak