The nature of Spring is to create objects in its container so that when you need an object, you can call the Spring container to get that object. Therefore, Spring seeks all the ways to support us in the creation of objects in the container of the most easily.
We knew how to inject this object into another object, or we can say: put object dependencies on dependent objects, using the ref, list attribute, … In addition, Spring also helps us to place the object dependencies into the dependent object automatically using its Bean Autowiring.
With Bean Autowiring, we do not need to use the ref or list attributes anymore, … just write code that complies with Spring’s rules, and objects dependencies will be automatically injected into the dependent object.
There are three ways to use Autowiring Bean, which are:
- byName
- byType
- constructor
For better understanding, I will make an example. In this example, we will require Spring automatically put the Table object into the Room object. As follows:
I will use Java 17 for this example:
1 2 3 4 |
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties> |
Spring dependency is as follows:
1 2 3 4 5 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.2</version> </dependency> |
Room class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.huongdanjava.springbeanautowiring; public class Room { private Table table; public Room() {} public Room(Table table) { this.table = table; } public Table getTable() { return table; } public void setTable(Table table) { this.table = table; } } |
Table class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
package com.huongdanjava.springbeanautowiring; public class Table { private String code; public void setCode(String code) { this.code = code; } @Override public String toString() { return "Table [code=" + code + "]"; } } |
Application class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package com.huongdanjava.springbeanautowiring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Application { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); Room room = (Room) context.getBean("room"); if (room.getTable() != null) { System.out.println(room.getTable().toString()); } } } |
And declare the Table and Room objects in the Spring configuration file:
1 2 3 4 5 6 7 8 9 10 11 12 |
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="table" class="com.huongdanjava.springbeanautowiring.Table"> <property name="code" value="123456" /> </bean> <bean id="room" class="com.huongdanjava.springbeanautowiring.Room"> </bean> </beans> |
OK, now I will go one by one and tell you more about it!
byName
As you all know, every bean in a Spring container has its own id. Based on this, Spring specifies if the id of the object dependency (in this example is a Table object) is the same as the name of a variable in the dependent object (Room object) and when declaring the dependent object, we declare the attribute autowire=”byName”, so Spring will automatically put the object dependency into the dependent object via the setter method of the dependent object.
In our example, the id of the Table object is exactly the same as the table variable name in the Room object, so we just need to declare more for the bean room a property autowire=”byName”. Then, Spring will inject the Table object into the Room object for us.
The configuration of the Room object will be modified as follows:
1 2 |
<bean id="room" class="com.huongdanjava.springbeanautowiring.Room" autowire="byName"> </bean> |
At running, the program will produce the following results:
This has the disadvantage that if we later change the variable name of the dependent object, we must modify the id of the object dependency in Spring’s container and vice versa. Can you imagine it?
byType
This approach is applicable only to small projects where each object has only one bean in the Spring container. By changing the autowire=”byType” attribute when declaring a bean, Spring automatically puts the object dependency into the dependent object via the setter of the dependent object.
1 2 |
<bean id="room" class="com.huongdanjava.springbeanautowiring.Room" autowire="byType"> </bean> |
Result:
If you deliberately declare another bean of the object dependency as follows:
1 2 3 4 5 6 7 8 9 10 |
<bean id="table" class="com.huongdanjava.springbeanautowiring.Table"> <property name="code" value="123456" /> </bean> <bean id="table1" class="com.huongdanjava.springbeanautowiring.Table"> <property name="code" value="123456" /> </bean> <bean id="room" class="com.huongdanjava.springbeanautowiring.Room" autowire="byType"> </bean> |
Then it will run with an error:
constructor
Like the attribute autowire=”byType”, this method only applies when our object has only one bean in Spring’s container. Then, Spring will automatically put the object dependency into the dependent object through the constructor of the dependent object.
For example, we change the configuration of the bean room as follows:
1 2 |
<bean id="room" class="com.huongdanjava.springbeanautowiring.Room" autowire="constructor"> </bean> |
Result: