Hacker News new | past | comments | ask | show | jobs | submit login
Spring Dependency Injection Styles – Why I love Java based configuration (codecentric.de)
33 points by javinpaul on July 23, 2012 | hide | past | favorite | 14 comments



I've used Spring on and off for 7+ years now. It was a seachange for Java and I like it a lot but the Java-based configuration has a serious defect.

Spring supports two methods of dependency injection: constructor injection and setter injection. Guice (in comparison) favours constructor injection. I prefer constructor injection too. It means objects can't be instatiated in an invalid state (assuming you enforce preconditions) whereas with setter injection you have to rely on lifecycle methods (eg @PostConstruct) to enforce that.

With Java-based Spring configuration you create instances rather than define dependencies in terms of classes (as Guice does it). This is a problem for constructor injection but not for setter injection.

This means when you create an instance to satisfy a dependency you need to explicitly supply all the constructor arguments. Spring would otherwise figure out setter injection.

With Guice you associate classes instead so you don't need to explicitly call a constructor with all the arguments. For Java-based configuration IMHO Guice is much better in this regard.

Also, Java-based Spring configuration relies on the cglib library, which may or may not be a problem in certain environments (eg its not officially supported on AppEngine but in my experience works fine for this).

So if you like constructor injection you have two options: component scanning or XML.

Component scanning is slow. Too slow. For even a small number of objects (<100) I've reduced startup times from ~30 seconds to ~10 seconds just by switching to explicit construction.

XML is really the best choice here. One thing you may not realize is you don't need to specify all the dependencies in XML (setter or constructor). You simply do a definition like:

    <bean class="com.example.Foo" />
and

    public class Foo {
      @Inject
      public class Foo(Bar bar, AnotherBar anotherBar) { ... }
    }
and Spring will figure it out.

IMHO this is far better than Spring's Java-based configuration.

EDIT: to clarify, @Inject here is JSR330 DI annotations [1] so java.named.Inject not com.google.inject.Inject. As that page notes Guice now supports either form.

[1]: http://code.google.com/p/google-guice/wiki/JSR330


"So if you like constructor injection you have two options: component scanning or XML." I totally disagree with this limitation. I do favor constructor injection and I am always using it with Java based configuration, I never use setter injection (maybe sometimes for optional dependencies). Why should it be a problem that you need an instance for satisfying a dependency? It's only a problem if you have circular dependencies, but then something is wrong with your design.

All the rest is flavor we could discuss about for hours without getting to an end, but Spring's Java based configuration definitely doesn't have a problem with constructor injection.

Regards, Tobias


"So if you like constructor injection you have two options: component scanning or XML."

I only half agree that this is a limitation. I use as little component scanning as possible. I think it's better to scan for the configuration classes (hopefully there aren't many) and explicitly define the rest. I like this for two reasons, first for speed and second because everything is defined in a fairly central place. I can't tell you how many times I've been surprised by annotation based configuration.

Personally I like Spring's Java Configuration over Guice's. It's more flexible for my needs. Although I suppose that an argument could be made that that's the problem: configuration over convention.

I'm glad you mentioned the Guice style @inject is available with Spring now. I wasn't aware of that.


I'm on the polar opposite end of this. We component scan everything we can, and I couldn't be happier. I have never once been surprised by what annotation based config assembled for me.

So, approaches may vary.


How's does it compare to Google Guice? Are there any benifits of using a lightweight DI Engine over Spring?


On top of dependency injection out of the box Spring offers a lot more, like: Transaction Management, an MVC framework, JDCB templates, ...


The key phrase there being "out of the box". Guice does great transaction management, just pull in guice-persist. It integrates with servlets cleanly, just pull in guice-servlet.

The difference is mainly that Guice tries to be a library and Spring tries to be a framework. I, for one, like knowing that I'm not pulling in "the world" just to get dependency injection.

Guice at its core does one thing, and one thing well: dependency injection (and by extension, AOP). It does dependency injection far better than any Spring version I've used (see: constructor injection).


Yes, but sooner or later guice won't be enough and you'll use a framework anyway; then the integration mess begins. With the configuration in code/profiles in Spring 3.1 I don't see any real-world advantage to using guice.


Absolutely not. When core Guice "isn't enough", I just grab one of the many great tools that integrate with Guice (Jersey is one example). My DI tool remains my DI tool, and I use a library that provides bindings for it.


> Are there any benifits of using a lightweight DI Engine over Spring?

Well yeah, several.

You don't have to depend on a huge API (spring-core and everything else needed for spring-di) just to get one piece of functionality.

You can avoid using XML as application logic.

You can avoid singletons-as-default-behavior and mutable beans all over the place.

It will likely be faster.


Wasn't the java configuration what spring wanted to replace in the first place? The idea was to follow the inversion of control principle. Here's how wikipedia defines it:

>In software engineering, Inversion of Control (IoC) is an object-oriented programming practice where the object coupling is bound at run time by an assembler object and is typically not known at compile time using static analysis.


Spring's Java Configuration can mean a few different things.

One is using @Autowired, @Component, and friends to build up your context. One could argue this violates IoC, although I disagree, but that's actually not the interesting meaning.

The interesting meaning is the use of @Configuration and @Bean to replace XML-driven config with Java-driven config. Basically you can replace a Spring XML file with a Java class that creates the same beans and assembles them in the same way, but in cases where you need to do something awkward to create a Bean instance that would be trivial in Java, you just do the trivial thing in Java.

So you haven't lost any of the abstractness provided by IoC. Bean classes don't change at all. It's simply how they're assembled that changes. Instead of writing a giant set of XML files to create a giant set of POJOs and wire them together, you write a similar set of Java classes and have one less language to deal with.


> Instead of writing a giant set of XML files to create a giant set of POJOs and wire them together, you write a similar set of Java classes

This is how you would do it without spring. I suppose there must be an advantage of using @Configuration and @Bean instead of plain java, but what is it?


They give you automatic proxied/intercepted objects for things like Transaction management, asynchronous execution, general AOP, etc. If you're not using any of that, there's probably little to no advantage to using pure Java DI. But those things are really nice to have.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: