Spring Autowiring Example using XML


In the Spring framework, autowiring enable you for automatic dependency injection. The Spring container can autowire relationship between collaborating beans.

To do automatic dependency injection using XML based configuration metadata, you specify autowire mode for a bean definition with the autowire attribute of the <bean/> element. The autowiring functionality has four modes.

ModeExplanation
nono is the default. Bean references must be defined via a ref element.
byTypeAllows a property to be autowired if exactly one bean of the property type exists in the container. If more than one exists, a fatal exception is thrown. If there are no matching beans, nothing happens; the property is not set. It also calls the setter method.
byNameAutowiring by property name. Spring looks for a bean with the same name as the property that needs to be autowired. It internally calls the setter method.
constructorSimilar to byType, but applies to constructor arguments. If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised.

Note: Autowiring functionality allows you to inject only secondary type’s value, it is not applicable for primitive type’s value.

How does it work?

If you apply autowire for any class, it will read all the parameters of the same class. And for that parameter, if there is setter method or constructor, it will treat that parameter as a dependent parameter.

Let’s check the complete example of all modes one by one.

Project Structure

Have a look of project structure in Eclipse IDE.

Spring autowiring example using XML

Spring Beans

In my example, I have created two classes Country and State. The Country class has secondary type dependency of State class.

State.java
package org.websparrow.beans;

public class State {

	//Generate setters and getters...
	private String stateName;
}
Country.java
package org.websparrow.beans;

public class Country {

	// generate setters...
	private State state; // secondary type

	public void setState(State state) {
		this.state = state;
	}

	// print injected value on the console log
	public void display() {
		System.out.println("State name is: " + state.getStateName());
	}
}

To make it more clear, I have divided beans configuration file in multiple parts.

Autowire – no

If autowire="no", Spring will not inject the values automatically, we need to configure it via ref attribute manually. And the configuration file looks like as given below.

<bean id="st" class="org.websparrow.beans.State">
    <property name="stateName" value="Uttar Pradesh" />
</bean>

<bean id="country" class="org.websparrow.beans.Country" autowire="no">
    <property name="state" ref="st" />
</bean>

Autowire – byType

If you apply autowire="byType", it will search its dependent type where you applied autowiring. In my example, I have applied autowire on Country class that has the dependency of State class. In this case, Spring container will search its type in all the document and the following configuration works fine.

<bean id="s" class="org.websparrow.beans.State">
    <property name="stateName" value="New Delhi" />
</bean>

<bean id="country" class="org.websparrow.beans.Country" autowire="byType" />

Now the problem is if the configuration file contains more than one eligible object of the same type.

<bean id="s" class="org.websparrow.beans.State">
    <property name="stateName" value="New Delhi" />
</bean>

<bean id="s1" class="org.websparrow.beans.State">
    <property name="stateName" value="Uttar Pradesh" />
</bean>

<bean id="country" class="org.websparrow.beans.Country" autowire="byType" />

In the above configuration, there is an ambiguity problem that means Spring unable to identify which State class object reference pass to Country class and it will throw the exception.

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException:
	Error creating bean with name 'country' defined in class path resource [spring-byType.xml]:
	Unsatisfied dependency expressed through bean property 'state'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
	No qualifying bean of type 'org.websparrow.beans.State' available: expected single matching bean but found 2: state,state1
		at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1439)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
	No qualifying bean of type 'org.websparrow.beans.State' available: expected single matching bean but found 2: state,state1
		at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:215)

To resolve the ambiguity problem, Spring framework will provide one more attribute of <bean/> element i.e. autowire-candidate. By default, its value is true. If you changed its value false, it will not allow the bean to participate in autowiring. And the below configuration works fine.

<bean id="s" class="org.websparrow.beans.State">
    <property name="stateName" value="New Delhi" />
</bean>

<bean id="s1" class="org.websparrow.beans.State" autowire-candidate="false">
    <property name="stateName" value="Uttar Pradesh" />
</bean>

<bean id="country" class="org.websparrow.beans.Country" autowire="byType" />

Autowire – byName

If autowire="byname", Spring container will search reference name along with its type/name. In this case there is no chance to get ambiguity problem because the bean id name should be unique throughout the application. It will throw the Null Pointer Exception if it unable to find the declared reference name. Following configuration works fine.

<bean id="state" class="org.websparrow.beans.State">
    <property name="stateName" value="New Delhi" />
</bean>
	
<bean id="country" class="org.websparrow.beans.Country" autowire="byName" />

If there is more one object of the same type available, it will work fine because id name must be unique throughout the application. Check this also.

<bean id="state" class="org.websparrow.beans.State">
    <property name="stateName" value="New Delhi" />
</bean>

<bean id="state1" class="org.websparrow.beans.State">
    <property name="stateName" value="Uttar Pradesh" />
</bean>

<bean id="country" class="org.websparrow.beans.Country" autowire="byName" />

Autowire – constructor

To test the autowire="constructor", create another bean City and its parameterized constructor with State reference.

City.java
package org.websparrow.beans;

public class City {

	private State state;

	// parameterized constructor
	public City(State state) {
		this.state = state;
	}

	public void print() {
		System.out.println("Varanasi is a city in " + state.getStateName() + " state.");
	}
}

Now, as we know that constructor internally will use byType mechanism. The following configuration works fine.

<bean id="s1" class="org.websparrow.beans.State" >
    <property name="stateName" value="Uttar Pradesh" />
</bean>

<bean id="city" class="org.websparrow.beans.City" autowire="constructor" /> 

Because it internally uses the byType, so there is a chance to get ambiguity problem. It can also resolve by applying autowire-candidate="false".

Run it

To test the autowiring, create a Test class and load the configuration one by one.

Test.java
package org.websparrow.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.websparrow.beans.City;
import org.websparrow.beans.Country;

public class Test {
	public static void main(String[] args) {
		
		//ApplicationContext context = new ClassPathXmlApplicationContext("spring-no.xml");
		//ApplicationContext context = new ClassPathXmlApplicationContext("spring-byName.xml");
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-byType.xml");
		Country c = (Country) context.getBean("country");
		c.display();

		/*
		ApplicationContext context1 = new ClassPathXmlApplicationContext("spring-constructor.xml");
		City city = (City) context1.getBean("city");
		city.print();
		*/
	}
}
Output:

You will get the same result on your console log for autowiring no, byName, and byType.

State name is: New Delhi

And in case of the constructor, you will get the following.

Varanasi is a city in Uttar Pradesh state.

Download Source Code: spring-autowiring-example-using-xml


Similar Posts

About the Author

Atul Rai
I love sharing my experiments and ideas with everyone by writing articles on the latest technological trends. Read all published posts by Atul Rai.