My case against autowiring
Autowiring is a particular kind of wiring, where injecting dependencies is not explicit but actually managed implicitly by the container. This article tries to provide some relevant info regarding disadvantages of using autowiring. Although Spring is taken as an example, the same reasoning can apply to JavaEE’s CDI.
Autowiring comes into different flavors:
- Autowiring by type means Spring will look for available beans that match the type used in the setter. For example, for a bean having a
setCar(Car car)method, Spring will look for a
Cartype (or one of its subtype) in the bean context.
- Autowiring by name means Spring search strategy is based on beans name. For the previous example, Spring will look for a bean named
carregardless of its type. This both requires the bean to be named (no anonymous bean here) and implies that the developer is responsible for any type mistmatch (if the
carbean is of type
Autowiring is also possible for constructor injection.
Autowiring through XML configuration
Let’s first dispel some misconceptions: autowiring does not imply annotations. In fact, autowiring is available through XML since ages and can be enabled with the following syntax.
This means Spring will try to find the right type to fill the dependency(ies) by using setter(s).
Alternative autowire parameters include:
- by name: instead of matching by type, Spring will use bean names
- constructor: constructor injection restricted to by-type
- autodetect: use constructor injection, but falls back to by-type if no adequate constructor is found
Autowiring through annotations configuration
Available annotations are the following:
|org.springframework.bean.factory.@Autowired||Wires by type||Spring 2.5+|
|javax.annotation.@Resource||Wires by name||JavaEE 5+|
|javax.inject.@Inject||Wires by type||JavaEE 6+|
|javax.inject.@Qualifier||Narrows type wiring||JavaEE 6+|
Dependency Injection is all about decoupling your classes from one another to make them more testable. Autowiring through annotations strongly couples annotated classes to annotations libraries. Admittedly, this is worse for Spring’s @Autowired than for others as they are generally provided by application servers.
Why it is so bad after all?
Autowiring is all about simplifying dependency injection, and although it may seem seductive at first, it’s not maintainable in real-life projects.
Explicit dependency injection is – guess what, explicitly defining a single bean to match the required dependency. Even better, if Java Configuration is used, it is validated at compile time.
On the opposite, autowiring is about expressing constraints on all available beans in the Spring context so that one and only one matches the required dependency. In effect, you delegate wiring to Spring, tasking him to find the right bean for you. This means that by adding beans in your context, you run the risk of providing more than one match, if your previous constraints do not apply to the new beans. The larger the project, the larger the team (or even worse, the number of teams), the larger the context, the higher the risk.
For example, imagine you crafted a real nice service with a single implementation, that you need to inject somewhere. After a while, someone notices your service but creates an alternative implementation for some reason. By just declaring this new bean in the context, along with the former, it will break container initialization! Worse, it may be done in an entirely different part of the application, with seemingly no link with the former. At this point, good luck to analyze the reason of the bug.
Note that autowiring by name if even worse, since bean names have a probability of collision, even across different type hierarchies.
Autowiring is bad in Spring, but it is even worse in CDI where every class in the classpath is a candidate for injection. By the way, any CDI guru reading this post care to explain why autowiring is the only way of DI? That would be really enlightening.
In this post, I tried to explain what is autowiring. It can be used all right, but now you should be aware of its con. IMHO, you should only use it for prototyping or quick-and-dirty proof of concepts, everything that can be discarded after a single use. If really needed, prefer wiring by type over wiring by name as at least it matching doesn’t depend on a String.