Today I had an exchange with an erstwhile colleague, one of those talented few equally comfortable in C++ and Java, great with demanding clients and fellow developers. He asked me for thoughts on Spring dependency injection. Branching out a bit, I replied:
Matter of taste/opinion.
Some things I prefer:
- Avoid setter injection if at all possible. I want my beans to be finished after DI, not changeable at runtime on accident (very nasty bug to track down) Constructor injection most preferred, followed by field
- Use standard annotations rather than Spring ones (
@Valueis needed for injected configuration if you're not using a dedicated configuration object
- Spring Java configuration beats XML almost all the time
- If the program doesn't need Spring DI, I prefer using Guice or Dagger. They're simpler, everything is at compile time, and error messages are better. The Spring non-DI libraries play fine with others (e.g., spring-jdbc)
- Avoid mixing business objects with wiring unless it makes sense. For example, JdbcTemplate should be new'ed as needed, injecting only the DataSource. Injecting the template is an anti-pattern
- Do use Spring Boot or Dropwizard, et al, if it makes sense. Big time savers, lots of good integration prepackaged
- For webby programs (apps, services) remember to test unit, controller and integration separately. Spring boot intro page has excellent code examples
Things get more interesting with multiple configurations and with cloud. For example:
- Do you make separate builds for each env, or one build with multiple configurations? Latter is traditional in EE world, former much better for cloud (devops, immutable, unikernel, etc)
- Do you pull in configuration externally, e.g., Spring Cloud Config, Netflix Archaius or Apache Zookeeper. I like this approach, but more complex and overkill for simple programs. Nearly mandatory for microservices, and strong choice when in cloud
Did I answer fairly?