
Spring Dependency Injection Styles – Why I love Java based configuration - javinpaul
http://blog.codecentric.de/en/2012/07/spring-dependency-injection-styles-why-i-love-java-based-configuration/
======
cletus
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>

~~~
stitchy
"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.

~~~
jsolson
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.

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

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

~~~
peeters
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).

~~~
Radu
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.

~~~
peeters
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.

------
zupatol
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.

~~~
jsolson
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.

~~~
zupatol
> 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?

~~~
dimasg
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.

