Spring Autowired annotation

In my previous post I briefly introduced the concept of Spring’s @Autowired annotation. This post goes more in-depth about this annotation, and its importance when developing with the Spring framework.

Spring uses the @Autowired annotation when it determines where it needs to inject a given @Bean. You can see this in the example below:

This example uses @Autowired on a private member variable referenced via class. In this example, the @Component is on the WeatherService class. The DependencyInjectionWithSpring class references the WeatherService class directly. I’ve annotated this reference with the @Autowired annotation. Spring then knows that it needs to find a bean (component) that matches. In this case, it finds the WeatherService class and injects it into the DependencyInjectionWithSpring class.

You can also reference with @Autowired via interface:

Here, I change the WeatherService class to be named WeatherServiceImpl, and have it implement the WeatherService interface, which I’ve also defined. DependencyInjectionWithSpring now references this interface (WeatherService), and the @Autowired annotation stays. Spring then knows that it needs to find a bean/component that implements the WeatherService interface. It finds the WeatherServiceImpl class and injects it into the DependencyInjectionWithSpring as a dependency (weatherService).

Field X in Y required a single bean, but 2 were found

What happens if we have multiple beans (components) that implement the same interface? Like this:

Both SunnyWeatherServiceImpl and CloudyWeatherServiceImpl implement the WeatherService interface. The DependencyInjectionWithSpring class depends on an implementation of WeatherService. Both of these classes would work, since they implement that interface. Spring is aware and manages both of these classes, since they are annotated with the @Component annotation. How does Spring know which one to choose? Let’s run the application and see what happens:

The application is unable to start. Spring can’t determine which bean to set for the weatherService.

How do I fix this?

To resolve this issue and tell Spring which bean to use in this situation, we have a few options.

The first option is to follow the first suggestion given in the exception:

Consider marking one of the beans as @Primary…

The @Primary annotation can be used to indicate to Spring which bean to use. In this case, I add the @Primary annotation to the SunnyWeatherServiceImpl:

Now when I run the application, it starts up with no errors and runs as expected, injecting the SunnyWeatherServiceImpl (the one with the @Primary annotation) into the DependencyInjectionWithSpring class.

There’s another option that Spring gives us, as mentioned in the error message from above:

or using @Qualifier to identify the bean that should be consumed

@Qualifier is a Spring annotation that allows us to tell Spring which bean we want to inject. See below:

Pay particular attention to the DependencyInjectionWithSpring class. The weatherService dependency in this class is now annotated with @Qualifier(value="cloudyWeatherServiceImpl"). This tells Spring to use the cloudyWeatherServiceImpl bean when injecting this dependency.

Now when I run the application, again it starts up with no errors and runs as expected. This time, I told Spring to use the cloudyWeatherServiceImpl class and it prints out The weather is cloudy with a 90% chance of rain as expected.

There’s yet another way to indicate to Spring which bean to inject. This is by naming the variable of the dependency the name of the class we want to inject. Like so:

Here, the WeatherService interface gets the name cloudyWeatherServiceImpl. This tells Spring that I want to inject the bean with the name cloudyWeatherServiceImpl. When I run this code, the application again starts up with no problems, and I again get the expected output.

Summary

Spring’s @Autowired annotation is used to indicate where to inject a Spring-managed bean. The @Primary annotation allows us to indicate which bean to use when multiple beans that match are present. The @Qualifier annotation allows us to specify a specific bean to inject on a given dependency. Finally, we learned that we can name the dependency with the bean name to also specify which bean to inject.

2 Replies to “Spring Autowired annotation”

  1. Hey Dustin, great blog with some good reads. I’ve ran into a few ‘java’ purists who insist that you ought to use @Inject rather than @Autowired. @Inject is introduced by the Java CDI in J EE 6; The theory is that if you use @Inject rather than @Autowired you could conceivably swap out your dependency injection library without having issues. Now I don’t know exactly where I stand on the issue because I’m primarily a Spring guy and once I start using it it goes pretty deep. I don’t mind being married to spring because they offer so much goodness. But seeing as we’re using DI to be less coupled maybe it makes more sense to be ‘less coupled to spring’ where possible. Thoughts??

    Also I recently read an article by a great Spring developer, Petri Kainulainen, who helped me to see the light on why field injection is bad. IMO its worth a read (https://www.petrikainulainen.net/software-development/design/why-i-changed-my-mind-about-field-injection/). The gist of it is that when all you have to do to add dependencies to a class is add ‘@Autowired MyService someService’ … its easy to look past the fact that you’re perhaps missing a crucial design problem. I’d love to hear your thoughts here too

  2. Hey Joey! Great questions!

    For your first question — I prefer to use @Inject for the very reason you mention: it makes my code less coupled to Spring itself. However, there are some limitations in going to the JSR-330 variants (see http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#beans-standard-annotations-limitations). In particular, the @Inject annotation has no ‘required=false’ option (and thus mandates the bean be fulfilled at startup time, else an exception is thrown). Also, I don’t particularly like the naming of the @Named annotation — to me, @Component is more descriptive. But besides those points, I prefer the JSR-300 variants myself.

    For #2 — I appreciate you pointing me to Petri’s blog post, that was a good read. I see where he’s coming from and have seen it done both ways. In fact, at my current job I frequently jump between two projects from two different teams — one uses field injection and the other constructor. With field injection there is less code (the constructor really is unneeded in this scenario), and the class reads ‘cleaner’ because of this. When I look through the classes set up in this manner I can quickly see their dependencies, and more quickly get to the ‘meat’ of the class. A downside to this is that an outside agent (Spring) is aware of, and is required to be aware of, state that I have declared to be private. Not good design, IMO. I personally prefer constructor injection, and not necessarily for the same reasons that Petri does (though I see his point). I prefer constructor injection because through it I can express the required dependencies that the class needs, in a first-class way (i.e. its public constructor). To me, that is the purpose of the constructor — to provide the class with the dependencies it requires. I prefer to trade a little bit more code for further clarity that helps me express intent, in a way that is supported by the language.

    Thanks again for your questions — hope you are doing well.

    -Dustin

Leave a Reply

Your email address will not be published. Required fields are marked *