That Depends

Over the last several days, I’ve been fiddling with SnipSnap, trying to add new features. One of the key parts of SnipSnap is an underlying component container called PicoContainer. PicoContainer is, in many ways, similar to the BeanFactory concept in Spring and it’s one of those new-fangled containers that exploits the pattern of dependency injection.

Until now, all of my playing with dependency injection has been with Spring. Pretty much all of the examples of Spring dependency injection involve what’s apparently known as “setter injection”. For my part, I find this kind of dependency injection extremely intuitive because its based on two things that I’m very familiar with:

  1. The JavaBeans specification
  2. Java Reflection

(Yeah, sure, those two things are hugely related, I know).

I think one of the reasons Spring’s BeanFactory was so easy to get my head around is that it seems like a natural extension to the many types of bean/reflection-based configuration utilities I’ve written many times over. Take a property file or XML file and reflect it on to a bunch of JavaBeans. Simple, straightforward, and powerful.

One of the things that strikes me as different in the way one uses PicoContainer is that it seems to favour a variant of dependency injection called constructor injection (Fowler’s article, which I’ve linked to, above, talks about constructor and setter injection as well).

It turns out that Spring can support constructor injection. Imagine that I’ve got a constructor like so:

public class MyComponent {

  public MyComponent(SomeRequiredBean bean) {
    this.bean = bean;
  }

  ...
}

If this is the only constructor, then unfortunately the MyComponent class isn’t really a JavaBean (JavaBeans are required to have a default no-args constructor).

But that doesn’t stop me from using it with Spring. I can configure my Spring XML file, like so:

<beans>
  <bean name="myComponent"
    class="com.example.spring.MyComponent"
    singleton="true">
     <constructor-arg>
       <ref bean="myBean"/>
     </constructor-arg>
  </bean>
  <bean name="myBean"
     class="com.example.spring.SomeRequiredBean"
     singleton="true">
  </bean>
</beans>

(Speaking only for myself, I find it annoyingly jarring to know that MyComponent is not, in fact, a bean, and yet my XML file proudly defines it in an XML bean tag).

The PicoContainer people make the case that constructor injection is an ever-so-much better way of writing components. Even Fowler weighs in on the side of constructor injection. After several days of playing with PicoContainer, I find myself unhappy with the approach.

It’s certainly true that when I made the transition from C++ to Java, I wrestled a lot with some of the central ideas in the JavaBeans specification — such as the idea that you could instantiate an object that was not yet considered to be fully initialized (the IllegalStateException came into existence because of the JavaBeans specification). But I’ve come to appreciate the power of good, old-fashioned JavaBeans.

But as a result, I’m less persuaded by the PicoContainer argument in favour of constructor injection. Part of it is their implementation; I feel like the work that the container is doing is less clear to me. Maybe it’s just a familiarity of approach thing, but I find myself annoyed at the obfuscation about what’s being passed into the constructor.

And I really don’t like the fact that constructor arguments don’t have names (or at least you can’t introspect the names). Properties have both names and types. But constructor arguments just have types. PicoContainer just looks for something (anything!) that’s the right type and passes it in to the constructor. That seems all manner of wrong to me.

I mean, take this example: in the last project we worked on, we needed to talk to two different databases. We were using Hibernate, so we had several components (in this case, DAOs) that depended on a Hibernate SessionFactory. Because we had two session factories, component type isn’t enough information to distinguish which of the two we want to inject — we need to also name the two factories.

I’ve been crawling through the PicoContainer documentation just trying to figure out if this is even possible. It certainly doesn’t seem to be obvious enough that the documentation shows a clear example.

It's only fair to share...
Share on FacebookGoogle+Tweet about this on TwitterShare on LinkedIn

Leave a Reply