Autowiring is a technique to wire the beans together. Specially, when there are many dependencies, all of the dependencies can be managed easily using Autowiring.
Autowiring can be performed in several methods, here are the following methods it can be done:
In this example we are going to use the following classes, interface and XML file.
Employee - Interface
package com.kasibsblog.spring.test;
public interface Employee {
public void print(String name, int salary, String company);
}
FullTimeEmployee - Class
package com.kasibsblog.spring.test;
public class FullTimeEmployee implements Employee {
public void print(String name, int salary, String company) {
System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ", "+ "Type : Full-Time");
}
}
PartTimeEmployee - Class
package com.kasibsblog.spring.test;
public class PartTimeEmployee implements Employee {
public void print(String name, int salary, String company) {
System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ", "
+ "Type : Part-Time");
}
}
AbCompany - Class
package com.kasibsblog.spring.test;
public class AbCompany {
private FullTimeEmployee fulltime;
private PartTimeEmployee parttime;
public void setFulltime(FullTimeEmployee fulltime) {
this.fulltime = fulltime;
}
public void setParttime(PartTimeEmployee parttime) {
this.parttime = parttime;
}
public void printFullTime(String name, int salary, String company){
fulltime.print(name, salary, company);
}
public void printPartTime(String name, int salary, String company){
parttime.print(name, salary, company);
}
}
Main - Class
package com.kasibsblog.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("com/kasibsblog/spring/test/beans/beans.xml");
AbCompany abcompany= (AbCompany) context.getBean("abcompany");
abcompany.printFullTime("Sue", 12000, "Ab Company");
abcompany.printPartTime("Mary", 10000, "Ab Company");
((ClassPathXmlApplicationContext) context).close();
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="init" default-destroy-method="destroy"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany">
</bean>
<bean id="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
</bean>
<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
</beans>
Now let's look at different modes of autowiring.
Here the fulltime and partime beans areselected as the default-autowire-candidates. It is a comma seperated list also note that the list cannot contain any white spaces.
Autowiring can be performed in several methods, here are the following methods it can be done:
- byType
- byName
- constructor
- default
In this example we are going to use the following classes, interface and XML file.
Employee - Interface
package com.kasibsblog.spring.test;
public interface Employee {
public void print(String name, int salary, String company);
}
FullTimeEmployee - Class
package com.kasibsblog.spring.test;
public class FullTimeEmployee implements Employee {
public void print(String name, int salary, String company) {
System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ", "+ "Type : Full-Time");
}
}
PartTimeEmployee - Class
package com.kasibsblog.spring.test;
public class PartTimeEmployee implements Employee {
public void print(String name, int salary, String company) {
System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ", "
+ "Type : Part-Time");
}
}
AbCompany - Class
package com.kasibsblog.spring.test;
public class AbCompany {
private FullTimeEmployee fulltime;
private PartTimeEmployee parttime;
public void setFulltime(FullTimeEmployee fulltime) {
this.fulltime = fulltime;
}
public void setParttime(PartTimeEmployee parttime) {
this.parttime = parttime;
}
public void printFullTime(String name, int salary, String company){
fulltime.print(name, salary, company);
}
public void printPartTime(String name, int salary, String company){
parttime.print(name, salary, company);
}
}
Main - Class
package com.kasibsblog.spring.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("com/kasibsblog/spring/test/beans/beans.xml");
AbCompany abcompany= (AbCompany) context.getBean("abcompany");
abcompany.printFullTime("Sue", 12000, "Ab Company");
abcompany.printPartTime("Mary", 10000, "Ab Company");
((ClassPathXmlApplicationContext) context).close();
}
}
beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
default-init-method="init" default-destroy-method="destroy"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany">
</bean>
<bean id="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
</bean>
<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
</beans>
Now let's look at different modes of autowiring.
1. byType
Autowiring is done by using the data-type. It tries to match exactly a bean per data-type, if it finds more than a bean of the same type then an exception is thrown, also known as "Autowiring ambiguity".
<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="byType">
</bean>
</bean>
Assume that there are two beans of FullTimeEmployee as:
<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
<bean id="fullTime2" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
</bean>
In this case, an exception would be thrown.
2. byName
Autowiring byName uses the the bean name or the bean id to wire the beans together.
<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="byName">
</bean>
<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
<bean name="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
</bean>
<bean name="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
</bean>
3. constructor
<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="constructor">
</bean>
The abcompany bean autowiring property is now set to constructor. The ABCompany class should include a two argument constructor, for this example.
public AbCompany(FullTimeEmployee fulltime, PartTimeEmployee parttime){
this.fulltime = fulltime;
this.parttime = parttime;
}
this.fulltime = fulltime;
this.parttime = parttime;
}
The beans should match both the arguments specified in the in the constructor, otherwise it will thrown an error.
Assume that the bean with id - fulltime, has the class set to AbCompany. This will result an ambiguity as the abcompany been autowired by constructor.
<bean id="fullTime" class="com.kasibsblog.spring.test.AbCompany">
</bean>4. default
Spring allows us to set a default autowiring which will be activated for the specified XML configuration file.
The default autowiring should be added to the beans tag in the configuration file, not the bean tag.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType">
</beans>
In the above sample code, I have selected the default autowiring method as byType. We can also specify any one of the above discussed methods.
Moreover, assume that there are two beans that belongs to FullTimeEmployee class. For example,
<bean name="fulltime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
<bean name="fulltime2" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
In this case, an exception would be thrown since that Spring cannot detect which bean to select from the two beans. In order to eliminate this ambiguity we can specify what bean should be used to wire with the "abcompany" bean.
We can achieve this by using the default-autowing-candidates property of the beans tag.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType" default-autowire-candidates="fulltime,parttime">
</beans>
The default autowiring should be added to the beans tag in the configuration file, not the bean tag.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType">
</beans>
In the above sample code, I have selected the default autowiring method as byType. We can also specify any one of the above discussed methods.
Moreover, assume that there are two beans that belongs to FullTimeEmployee class. For example,
<bean name="fulltime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
<bean name="fulltime2" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>
In this case, an exception would be thrown since that Spring cannot detect which bean to select from the two beans. In order to eliminate this ambiguity we can specify what bean should be used to wire with the "abcompany" bean.
We can achieve this by using the default-autowing-candidates property of the beans tag.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byType" default-autowire-candidates="fulltime,parttime">
</beans>
Here the fulltime and partime beans areselected as the default-autowire-candidates. It is a comma seperated list also note that the list cannot contain any white spaces.
Using wildcards to specify default-autowire-candidates
Wildcards can be used to specify the default candidates, an asterisk(*) is used as the wildcard character.
In our example, both the beans end with "time" - fulltime & parttime. The code can be changed to
default-autowire-candidates="*time"
Hi Kasib. Thank you for your topic.
ReplyDeleteBut why did you use out-of-date XML configuration?
Hi Sergey,
ReplyDeleteThanks for the feedback. I used XML configuration to explain the behind the scenes of Autowiring. My next post will be on Autowiring with Annotations and don't forget to check it out.