Follow Slashdot blog updates by subscribing to our blog RSS feed

 



Forgot your password?
typodupeerror
×
Programming IT Technology

Dependency Injection with AspectJ and Spring 48

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'"
This discussion has been archived. No new comments can be posted.

Dependency Injection with AspectJ and Spring

Comments Filter:
  • Who wrote that? The Marketing Department?
  • Good News! (Score:5, Funny)

    by maxcray ( 541911 ) <cnystrom@gmail.com> on Wednesday December 14, 2005 @02:55AM (#14254340)
    This is good news! I have long wanted to "encapsulate the details of middleware service invocations".
  • by advocate_one ( 662832 ) on Wednesday December 14, 2005 @03:11AM (#14254387)
    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'
    • Yes.

      Although I do agree that whoever wrote the article could have used easier words. You have to already be familiar with Dependency Injection (or IoP) and AoP to actually understand. Which sorta voids the purpose of the article.
    • Re:My brain hurts... (Score:5, Informative)

      by Kj0n ( 245572 ) on Wednesday December 14, 2005 @04:01AM (#14254560)
      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 [martinfowler.com], by Martin Fowler. It's older than the one mentioned in the story, but still relevant.
      • To summarize Fowler's summary:

        It's a complicated way of getting around some problems caused by Java; problems which don't occur in dynamic languages such as Ruby.

        • It's a complicated way of getting around some problems caused by Java; problems which don't occur in dynamic languages such as Ruby.


          Please explain ... probably Ruby might have advantages there over Java, but surely not because it is dynamic typed. What do you mean by "those probelms"? Please give an example!

          angel'o'sphere
          • 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

            • by maraist ( 68387 ) * <michael.maraistN ... m.com minus poet> on Wednesday December 14, 2005 @04:10PM (#14259108) Homepage
              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
              • The idea of Inversion of Control is that the thing that needs a service should NEVER configure that service.

                In that case, the article cited was incredibly badly written. What's more, I fail to see how the example given in Java achieves the supposed goal. How does that Spring XML file get written, if not by whoever is using the service code?

                • Other posters have explained this better than I, and the links will as well I'm sure.

                  But the idea is that in spring/pico/nanno/etc the configuration description is a deployment issue, not an application issue.. It's like editing /etc/X11/xorg.conf. By merely twiddling fields in a sample xml-configuration, you can dramatically alter what the entire product does. Mixing and matching sorters, data-repositories, inter-process communication tools, etc. It also allows a trivially easy way of mixing matching de
                • "the thing" is meant to the class, not a person. The class shouldn't know about which implementations of its components it should be using. Using inversion of control moves that responsibility away from your class.
              • I had first heard about the Law of Demeter and thought it to be a Good Thing, but lately I wonder.

                In Java Swing, from a JFrame object, you say

                myWidget = new MyWidget(this);

                getContentPane().add(myWidget, BorderLayout.CENTER);

                This is a blatent Demeter violation now, isn't it? Or is it only a Demeter violation of either the strong or the weak form of Demeter depending on whether invoking the function getContentPane() to return an internal object of the JFrame from a derived class is co

                • Well, I don't do a lot of GUI design.. Mostly HTML generation through servlets (or some other language structure).

                  From that, most of my code is layered separately between UI and application. In fact all HTML generation comes from JSP pages.. And even more, most of the HTML in that is segregated stle-sheets + JSP2.0-tag files (not to be confused w/ jsp-includes). And further, the basic framework of a JSP page is built from a sitemesh template (opensymphony.org). which means the content jsp page l
              • Yes, but ruby allows all kinds of stuff like this very simply by "reopening" the object and adding in your code as desired.

                Spring allows Java to inject code.

                Ruby has inate support for injecting code.

                class Hash
                  def to_s
                    return 'hello';
                  end
                end

                You can override any method from any point in the code.  This can be your best friend or worst enemy.  It will, however, make dependency injection trivial.
            • Sorry,

              but thats not right.

              finder = CSV::Reader.parse(File.open('movies.csv')) this line is a dependency. You obviously depend on CSV:: and you have hardcoded the dependency here.

              IoC or Dependency Injection is about how to avoid hardcoding dependencies between components.

              In IoC frameworks you usually use an external description file, e.g. an XML file (deployment descriptor) or an AOP code snipped.

              A generator or a runtime component would read that fiel and insert your line: finder = CSV::Reader.parse(File.op
              • It would be trivial to make the choice of CSV::Reader depend on an external config file if you want:

                chosenclass = File.open("config.txt").gets.chop
                finder = chosenclass.parse("movies.csv")

                The example *is* reusable. Those lines you pick out aren't part of the class library, they're an example of how you can call it with whatever class you like (even one chosen from a config file), without needing any kind of complicated scaffolding like in Java. I just put them in to demonstrate that the code actually works.

                T
                • Your example would look the same in Java (or any other stron typed language).

                  I simply don't understand which point you want to make ;-)
                  And as the core question was: Why is IoC easyer in Python than in Java? You failed IMHO to answer that question.

                  In Java your code would only look like this:

                  SomeType chosenclass = File.open("config.txt").gets.chop; // probably this is a call? Then add ()
                  SomeOtherType finder = chosenclass.parse("movies.csv");

                  Voila! Exactly the same simplicity like in Python, except that we add
                  • OK, so if you can read a class name from a config file and call that class, why is all that other stuff in the article necessary? I guess I'm still not getting the point of it all.
                    • The article is about this:

                      you have several classes that work together. Usually one or mroe of those classes would instanciate each otehr to get a net of objects. So at least one of them has the complete construction process of all objects involved in on of their constructors.

                      If a new class is ment to reuse this network, it has again a construction statment for the root class of the used network.

                      The more classes you have the ore are constructions, calls to new, clutterd as hardcoded dependencies all over you
            • Unlike some of the other comments here, I think you've basically got it. Examples in Java can be as simple as this, too: the "icing" from DI frameworks is that they generally use introspection and reflection to manage object instantiation and to "jsut work" against any set of classes that you'd like to instantiate and supply dependencies to. You can knock that up in Ruby pretty simply; it's as straightforward in Java, too, but the expression of the reflection code is typically more verbose.
    • 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...."
    • Rats, for a moment there I thought they came up with a new shot to fight cocaine addiction. No such luck...
    • Re:My brain hurts... (Score:2, Informative)

      by gedhrel ( 241953 )
      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 co
      • Having said that, I'm still not sold on AOP. My concern, I realise, is that AOP is prone to the same problem that makes people denigrate operator overloading (a language feature that I find particularly appealing): it's easy to write absolutely unmaintainable code using AOP. My gut instinct is that AOP is more prone to this than (say) operator overloading, since aspects are rather more widely distributed through source than the latter.

        I guess the conclusion (which is the one I also draw about operator overl
      • And this is different from inheritance wrapping into a translation class exactly how?
        • Implementation.

          I know this answer provides no value. I was guessing from the tone of your question that you don't really care to have it answered anyway.
        • Er. Ok. The way you implement concrete components (that reify an interface) may indeed utilise inheritance; depends on the language. Not sure what you mean by "translation class" - a wrapper?

          "Dependency Injection" doesn't really care about that. What it's concerned with is how particular components locate the other components they have to interact with.

          Possibilities: hard-coded instantiation -

          Foo foo = new Foo(); // not DI

          the same kind of thing, but using reflection

          Foo foo = (Foo) Class.forName(fooClass).ne
          • OOO! I get it know...

            So, it's exactly like what I've been doing with my object oriented approach to C coding, that doesn't make sense in OO languages because the syntax makes you lazily pick the non-DI way...
          • Ok, so I was completely wrong. It's more like what microsoft developers call intrinsic binding, rather than merely wraping a class in another class to translate between two disparate systems. It also contains some aspects of Microsoft's late binding in that it doesn't matter where a class is at compile time (or even if you have a copy of the class or it's wrapper installed on your machine at compile time).
            • Late binding is exactly it. Lots of ways to do it: dependency injection is one approach. Shoving implementations into a tree/namespace of COM objects at well-known locations is another way. The important thing is that the burden of selecting the implementation and instantiating it is not on the class that uses it, but on the framework that provides it.
  • Finally, with more articles like this I can say that reading Slashdot is actually good for my thesis on AOP.
  • Spring (Score:2, Insightful)

    by ackdesha ( 572569 )
    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 j

  • by yagu ( 721525 ) * <yayaguNO@SPAMgmail.com> on Wednesday December 14, 2005 @08:20AM (#14255318) Journal

    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

    • IANAAOP

      OK, I think that it's fair to say that AOP is still very much at the cutting edge of developement in the java community.

      Essentially the idea with AOP is that you increase the modularity and decrease the coupling of components in your application. An example of this would be Logging.

      Now most (if not all) apps need to have logging code of one sort or another. This means that the code necessary to log to whichever system (commons-logging, log4j etc in the java world) you use tends to touch all of


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

      Every major development uses either J2EE (JBoss, WebSpehre or what ever)
      OR: Spring + Hybernate + AspectJ

      Why don't you google for it ;D

      And yes, if you code in java you should get familiar with at least one of those.

      angel'o'spehre
      • Aack.. You got me at both ends..

        j2ee != jboss/websphere..
        EJB == jboss/websphere.
        j2ee incluedes servlets (tomcat), mail, encryption and transactions..

        Then on the other extreme, you groups AOP w/ spring+hibernate.. evil evil man.

        I find myself in the situation that when I move on to bigger and more profitable projects, my legacy code gets taken over by outsourced Indian groups, and the shere number of buzz words involved is enough to make their heads explode I should think.
    • Sure, I'm building one right now. You can't get to it, though, and I'm not really allowed to tell you much about it.

      Most of these applications aren't high-profile public projects. Typically, you're talking about internal business systems.

      Overall, it's important to remember: Your belief in the value of a given technique has no effect on the actual value therein.

Where there's a will, there's an Inheritance Tax.

Working...