Java Spring - Bean Autowiring
In this tutorial, we will learn to implement Bean Autowiring and provide relevant dependencies. We will also learn to write the correct configuration which will be annotation based.
As already stated in our previous articles of the series, Spring framework is an open source Java platform that provides MVC infrastructure support for developing robust Java applications very easily and very rapidly using recommended MVC pattern.
How does Autowiring happens?
Now that we have learned to define our beans, Spring container can autowire them for us and manage them as well.
First, and most important—all Spring beans are managed. They "live" inside a container called the "application context."
Second, each application has an entry point to that context. Web applications have a Servlet, JSF uses a el-resolver, etc. Also, there is a place where the application context is bootstrapped and all beans autowired. In web applications this can be a startup listener.
Autowiring happens by placing an instance of one bean into the desired field in an instance of another bean. Both classes should be beans, i.e. they should be defined to live in the application context.
What is "living" in the application context? This means that the context instantiates the objects, not you. i.e. you never make new UserServiceImpl(). The container finds each injection point and sets an instance there.
In your controllers, you just have the following:
@Controller // Defines that this class is a spring bean
@RequestMapping("/users")
public class SomeController { // Tells the application context to inject an instance of UserService here
@Autowired
private UserService userService;
@RequestMapping("/login")
public void login(@RequestParam("username") String username, @RequestParam("password") String password) { // The UserServiceImpl is already injected and you can use it
userService.login(username, password);
}
}
A few things to take care of:
- In the applicationContext.xml always enable the <context:component-scan> so that classes are scanned for the @Controller, @Service, etc. components.
- The entry point for a Spring-MVC application is the DispatcherServlet, but it is hidden from us, and hence the direct interaction and bootstrapping of the application context happens behind the scene.
- UserServiceImpl should also be defined as bean—either using <bean id=".." class=".."> or using the @Service annotation. Since it will be the only implementor of UserService, it will be injected.
- Apart from the @Autowired annotation, Spring can use XML-configurable autowiring. In this case all fields that have a name or type that matches an existing bean automatically get a bean injected. In fact, that was the initial idea of autowiring, to have fields injected with dependencies without any configuration. Other annotations like @Inject or @Resource can also be used.
@Autowired
The @Autowired annotation allows us to skip configurations elsewhere of what to inject and just does it for you. Assuming the package is com.discoversdk.blogs you have to put this tag in your XML (application context file):
<context:component-scan base-package="com.discoversdk.blogs" />
This tag will do auto-scanning. Assuming each class that has to become a bean is annotated with a correct annotation like @Component (for a simple bean) or @Controller (for a servlet control) or @Repository (for DAO classes) and these classes are somewhere under the package com.discoversdk.blogs, Spring will find all of these and create a bean for each one.
This is done in 2 scans of the classes:
- The first time, it just searches for classes that need to become a bean and maps the injections it needs to be doing.
- On the second scan it injects the beans. Of course, you can define your beans in the more traditional XML file or with a @Configuration class, or any combination of the three. The @Autowired annotation tells Spring where an injection needs to occur. If we put it on a method setBlogFinder it understands (by the prefix set + the @Autowired annotation) that a bean needs to be injected.
In the second scan, Spring searches for a bean of type BlogFinder, and if it finds such a bean, it injects it into this method. If it finds two such beans you will get an exception. To avoid the exception, we can use the @Qualifier annotation and tell it which of the two beans to inject in the following manner:
@Qualifier("redBean")
class Red implements Color {
// Class code here
}
@Qualifier("blueBean") class Blue implements Color {
// Class code here
}
Or if you prefer to declare the beans in your XML, it would look something like this:
<bean id="redBean" class="com.discoversdk.blogs.Red"/>
<bean id="blueBean" class="com.discoversdk.blogs.Blue"/>
In the @Autowired declaration, we need to also add the @Qualifier to tell which of the two color beans to inject:
@Autowired
@Qualifier("redBean")
public void setColor(Color color) {
this.color = color;
}
If we want to avoid two annotations (the @Autowired and @Qualifier) we can use @Resource to combine these two:
@Resource(name="redBean")
public void setColor(Color color) {
this.color = color;
}
The @Resource spares us the use of two annotations and instead we only use one.
Lastly:
- Good practice would be to use @Inject instead of @Autowired because it is not Spring-specific.
- Another good practice would be to put the @Inject / @Autowired on a constructor instead of a method. If we put it on a constructor, we can validate that the injected beans are not null and fail fast when we try to start the application and avoid a NullPointerException when we need to actually use the bean.
So, to sum it up: The @Autowired annotation spares us the need to do the wiring by ourself in the XML file (or any other way) and just finds for us what needs to be injected where, and does that for us.
Disadvantages of Autowiring
There are not too many really, but there are some things to watch out for with Autowiring. Let’s quickly look at two of the disadvantages Autowiring presents:
- No control of programmer while the bean gets injected.
- It can’t be used for primitive and String values.
Autowiring modes
There are basically 5 modes in which Autowiring can be performed. These are:
- no : This is the default mode. This means no autowiring should take place. Let us look at an example,
<bean id="b" class="com.discoversdk.B"></bean>
<bean id="a" class="com.discoversdk.A" autowire="no"></bean>
- byName : This mode injects the object dependency based on the name of the bean. In such cases, the property name and the bean name must be equal. It internally calls the setter method. Let’s look at an example,
<bean id="b" class="com.discoversdk.B"></bean>
<bean id="a" class="com.discoversdk.A" autowire="byName"></bean>
- byType : This mode injects the object dependency based on type. So property name and bean name can differ. This also internally calls the setter method. Let us look at an example,
<bean id="b1" class="com.discoversdk.B"></bean>
<bean id="a" class="com.discoversdk.A" autowire="byType"></bean>
- constructor : In this mode, dependency is injected by calling the constructor of the class. It calls the constructor having the largest number of parameters. Let us look at an example,
<bean id="b" class="com.discoversdk.B"></bean>
<bean id="a" class="com.discoversdk.A" autowire="constructor"></bean>
- autodetect : This is a deprecated mode.
Conclusion
In this article, we learned about how to inject and autowire beans in Spring. We also had a look at what disadvantages wiring has. So let us know if you have any luck with autowire in Spring or have any questions. Leave a comment below!
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment