Slashdot Mirror


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'"

9 of 48 comments (clear)

  1. Good News! by maxcray · · Score: 5, Funny

    This is good news! I have long wanted to "encapsulate the details of middleware service invocations".

  2. My brain hurts... by advocate_one · · Score: 4, Funny
    honestly, does anyone actually understand what the heck they're going on about here???
    'facilitate advanced dependency injection scenarios.' [...]'Dependency injection encapsulates the details of resource and collaborator discovery, and aspects can (among other things) encapsulate the details of middleware service invocations'
    --
    Donald 'Duck' Dunn: We had a band powerful enough to turn goat piss into gasoline.
    1. Re:My brain hurts... by Kj0n · · Score: 5, Informative

      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.

    2. Re:My brain hurts... by ObsessiveMathsFreak · · Score: 2, Funny

      honestly, does anyone actually understand what the heck they're going on about here???

      More or less. Essentially the author is saying:

      "Buy My Book....Buy My Book...."

      --
      May the Maths Be with you!
    3. Re:My brain hurts... by gedhrel · · Score: 2, Informative

      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.

  3. Spring by ackdesha · · Score: 2, Insightful
    If you think you even might be involved in a new j2ee proj., a good book that explains much of this complexity (or maybe buzz) is Rod Johnson's (of Spring notoriety) J2EE without EJB. I think their movement suffers to some degree from over abstraction, but it does beat EJB and is my choice for j2ee development.

    I'd rather use RoR or any other dynamic language for web dev in general. However, there are still many business requirements that can come up (OLAP for one - Mondrian) that keep me coming back to j2ee for now.

    The Spring framework reduces IoC and AOP to configuration details (XML - blech) so you don't have to worry to much about the implementation. Very powerful I'm sure in the hands of a seasoned Spring user.

  4. one good project from this? by yagu · · Score: 2, Insightful

    Aside from more jargonism, can anyone cite one major application, one major project for which this was used?

    I'm signing up for my 10-year training plan to learn the terminology, jargon, etc.

    Then I'll consider if I even want to learn to apply it. Sheesh, this is embarrassing

  5. Re:Summarizing the summary by metamatic · · Score: 2, Informative

    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.

    require 'csv'

    class MovieLister
    attr_writer :finder

    def movies_directed_by(director)
    if not @finder
    raise "Finder not set before calling movies_directed_by"
    else
    result = @finder.collect {|dirname,movname| movname if dirname == director }
    result.delete(nil)
    return result
    end
    end
    end

    finder = CSV::Reader.parse(File.open('movies.csv'))
    lister = MovieLister.new
    lister.finder = finder
    puts lister.movies_directed_by('Stanley Kubrick')

    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
  6. Re:Summarizing the summary by maraist · · Score: 3, Interesting

    I'm sorry, but you are incorrect.

    Dependency injection has NOTHING to do w/ weak or strict type-safety (and, in fact, a concrete class is not required at all.. reflective interface handlers often can facilitate service needs). And if you use dyna-beans, then neither the producer or consumer ever even need an interface.

    Your example shows the exact flaw in coding that Inversion of Control (through setter/constructor injection) solves.

    Namely that you explicitly had to configure your dependencies. Yes, due to weak-types in such languages you could take almost any arbitrary code and plug it in to fullfill the server.. The fact still remains your code explicitly configured it.

    The idea of Inversion of Control is that the thing that needs a service should NEVER configure that service. It's the law of demiter. If I want to use some thing, I shouldn't need to know that it in turn uses something else. If I have to configure both the thing that I want to use AND the thing that it wants to use, then eventually all my code is convoluted (doing and configuring crap that has nothing to do with what I'm actually trying to do).

    If you simply take a step back and have something that uses the service configure the service, you'd still have to point some code to the thing that configured the service, so you're just moving the problem around (which is what your example does).

    Inversion of control allows you to define the entire application modularly where each module only cares about capabilities of external modules (not their configurations nor their nested dependencies). In your example, the type-weak language merely requires the positional arguments to be compatible (which, I agree is a very powerful thing.. Perl's "grep", "map" and "sort" commands are incredible). In java, it would require an explicit class (interface or conctrete).

    When you build your application this way, and you generalize your inter-component communication as genericly as possible (yes perl,ruby,python can much more easily genralize a service), then you can plug pieces together that were never originally meant to work together.

    Another very important aspect of IoC is that you can easily test each piece separately, as instead of an application-confired container, you have a testing-configured container which performs appropriate configurations suitable for testing and unit-isolation.

    With setter and constructor injection and through the use of interfaces, you facilitate mocking of 3'rd party services such that you completely skip all the complexity of side components and focuses very specificly on what a single component is doing.. You can test 'what would this module do if it's dependency returned something unexpected'.

    If you have a perl module that internally uses some other class, how could you easily test interaction with the other class (say a IO::File). Typically you create test files. But what about when it's a database or a web site.. Your unit tests get more and more complicated. Especially if what the module is doing has is really independent of the fact that it's using a URL or database.

    If instead the module was fully configured externally (no default configuration w/ zero-arg constructors or default package global variables), then you would be assured that you have full control over the environment of the module in question.

    Thanks to these types of interactions, the power of object-orientation can be exploited while at the same time using singletons (essentially context-specific global variables; an otherwise anti-pattern). This has a trade-off of faster execution time at the cost of a higher memory usage and slower startup time. The fact that IoC usually has a non-neglegable setup time often means that we lean towards singletons (which has implications on code design).

    Finally, the code you showed is fine for alternating configurations.. And for small tasks, the overhead of IoC is simply not justified. IoC really comes into it's own in very large p

    --
    -Michael