← Back to home

I am a bit puzzled by Martin Fowler’s description of the difference between IoC type 1 (interface injection):

class MovieLister implements InjectFinder…
  private MovieFinder finder;
  public void injectFinder(MovieFinder finder) {
    this.finder = finder;
  }

and IoC type 2 (setter injection):

class MovieLister…
private MovieFinder finder;
public void setFinder(MovieFinder finder) {
  this.finder = finder;
}

These two methods look exactly the same to me, except for the name of the method the initializes the component and the interface implemented by the first component (the second component could implement an interface as well).

Am I missing something?

Comments (15)

Anonymous

Type 1 relies on casting vs Type 2 relies on reflection. The difference is mostly in the container implementation.

Cedric

There is neither casting nor reflection in either of the two code snippets that I reproduced. Glad to see I'm not the only one confused.

Pinocio

When container injects dependency in the first case it will be "instanceof" followed by the cast, the second case will produce code looking for a Method" and its signature.

Jason Carreira

In the XWork implementation of IoC (very simple) instances are keyed off of the enabler Interface, as shown in what he's called Type 1, so I guess he'd call that Type 1. It basically just looks through the Interfaces implemented and looks for them in its registry. What I had previously heard referred to as Type 1 was the Avalon type config which ended up needing a dependency resolver to basically do service locator stuff to fulfill the dependency.

Robert Watkins

It's actually fairly simple: with setters, you have no assurance that the setter will be called once and only once. Some idiot might come along and call the setter again. Or, if you're not using the framework, some idiot may not call the setter in the first place. By using the constructor, you _know_ that the object is correctly made, and that immutable properties won't change.

Jason Carreira

Unless, of course, someone calls the constructor with null values...

Joe Duffy

Cedric, I share your confusion with the description of IoC 1 in Martin's article. According to the PicoContainer website, IoC type 1 (Contextualized Lookup, the new fancy schmancy name) pushes the dependency lookup and wiring down to the consumer service. (http://www.picocontainer.org/types-of-ioc.html) But, Martin's definition really doesn't illustrate this at all. His example, class MovieLister implements InjectFinder... public void injectFinder(MovieFinder finder) { this.finder = finder; } Should really be something along the lines of, class MovieLister implements InjectFinder... public void injectFinder(ServiceRegistry registry) { this.finder = (MovieFinder)registry.lookup(MovieFinder.class); } Or, am I confused as well? :) (As a side note, although IoC is very generic and perhaps a tad ambiguous from a descriptive standpoint, injecting - pun intended - new terminology consisting of big long words I think only serves to raise the barriers to entry and scare off the bulk of would-be adopters.)

Joe Duffy

Hmm, now that I think of it, "Inversion of Control" is pretty big, long, and scary as well...

Anonymous

"Type 1 relies on casting vs Type 2 relies on reflection. The difference is mostly in the container implementation." I meant that in your example, the container would do this for Type 1: ((InjectFinder) service).injectFinder(finder); compared with this for Type 2: and the container would: ServiceUtil.set(setterName, dependentService);

Anonymous

correction for previous comment: &ltservice id="movielister" class="MovieLister"&gt &ltproperty name="finder" serviceRef="moviefinder" /&gt &lt/service&gt ServiceUtil.set(parentService, propName, dependentService);

R.J.

Cedric - I think that it is an over-categorization myself, but the main differences can be seen between SpringFramework and Avalon. The only concrete difference is the interface implementation, and more specifically, the existance of the interface itself. SpringFramework injects dependencies based on Javabeans specifications (and reflection), Avalon uses instanceof on the known interface types and casting. They are considered different because of this. Are you missing something? No. I think it is really people trying to segregate and seperate themselves - uniqueness goes a long way. Avalon is a non-reflection implementation, that's all. The main advantage of Type-2 is you don't have to mitigate IOC concerns into the class file (by implementing interfaces for the container).

Frank Bolander

Isn't IOC, or whatever we're calling it here, a prime candidate for a "separation of concern" type of AOP solution. Basically, all the talk is having a push type of model to produce auto-wiring, auto-dependency, etc... Couldn't this whole problem be addressed through cross-cutting against the "new(..)" keyword. Let all the auto-wiring be triggered through this standard java keyword. A simple example: public aspect IOCAspect { pointcut creationAspect(): call(MovieFinder.new(..)); Object around():creationAspect(){ // Implement the Actual concrete instance Object newObject = ... whatevever factory return newObject; } } Then have a Container: public class MovieLister { MovieFinder object = new MovieFinder(); ... } The container becomes "auto-wired" through the creationAspect advice without any restrictions on Setter or Constructor "Dependency Injections".

Slava Imeshev

It's simple. If you don't name the method inject, it will be boring Inversion of Control and you couldn't talk about it it. It's not romantic at all. Personally I would like weared Data Transfer Object to be renamed to Data Teleport Object. This alone will make RMI trasnfers instant.

Mirko Novakovic

Cedric, for me there is one big difference between IoC-2 (setter) and IoC-3 (constructor): After the constructor is called, the object has all its properties and is ready to be called in IoC-3. In IoC-2 the constructor is called and the object is (maybe) not ready to be called, because some dependencies are missing. So in IoC-2 you have to implement something like a state: CREATED->CONFIGURED->READY In IoC-3 you don't need this state because after object creation the object has always the READY state. Mirko

Dan Weinreb

Cedric, I think you're right to be confused; I am too. The crucial point is where Fowler says "For simplicity's sake, I'll do it in code." If you "do it in code", then there's no interesting difference between the "setter" and "interface" patterns, and so the entire point is lost. The real question is whether the framework that uses "interface injection" (Avalon or whatever) was told something special about the InjectFinder interface, and, if so, what. In fact, the only reason that the whole topic is interesting enough to write about is because of the way these component framework architectures work. However, having never seen any of these frameworks, it's hard to compare and contrast the approaches; Fowler's brief introduction to the frameworks is too brief, especially in the case of Avalon. His example of a Spring XML file is confusing because at first glance it appears that the value of an "id" attribute of a "bean" element is the name of a Java interface. Only when you notice the lack of the package prefix do you realize that this is really a misleading coincidence (I think!); he should have given them different names. In the PicoContainer case, what am I supposed to assume that the following line of code means: pico.registerComponentImplementation(MovieFinder.class, ColonMovieFinder.class, finderParams); Does this mean that whenever anybody asks for an instance of MovieFinder interface, the framework will always use the ColonMovieFinder implementation and always pass in "movies.txt" to the constructor? Or does it mean that whenever anybody asks for an instance of the ColonMovieFinder class, the framework will always pass in "movies.txt" to the constructor? Or something else? When he starts talking about "service locators" he completely loses me. Why would a class with a broadly generic name like ServiceLocator just happen to have a method specifically about movies? If ServiceLocator is part of the movie world rather than part of the framework, it should have some better name. And from then on he makes the same "I'll do it in code" mistake.