Spring Autowiring using byType

In this article, we will walk through an example demonstrating ‘byType’ autowiring mode. In this autowiring mode, if data type of the bean is compatible with other bean defined in the configuration file then it will autowire it i.e.; inject those properties automatically.

When attribute autowire=“byType” is set in the <bean> element, then at runtime Spring injects the collaborating beans by inspecting the other beans defined in the configuration file with the compatible data type.

For Example,

If employee bean has a property named address, then setting autowire=“byType” inspects others beans defined in the configuration file with data type of that of address property in the Employee bean.

We will see a detailed example and its explanation below.

Technology Used

  • Java 1.7
  • Eclipse Kepler IDE
  • Maven 3.0.4
  • Spring-4.0.0-RELEASE

Mavenize or download required jars

Add Spring-4.0.0 dependencies to the pom.xml

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>

Folks who aren’t familiar with Maven concepts or don’t require maven for their project, can download the below jars individually from the spring site and include them in the classpath.

  • spring-core-4.0.0-RELEASE
  • spring-context-4.0.0-RELEASE
  • spring-beans-4.0.0-RELEASE
  • spring-aop-4.0.0-RELEASE
  • spring-expression-4.0.0-RELEASE
  • commons-logging-1.1.1
  • aopalliance-1.0

Let’s see coding in action

 

Create simple Spring beans Address and Employee

Address class

Simple & straight forward spring beans with four primitive properties and its getter/setters with one public method called “printAddressDetail()” to print the address details

Address.java

package com.spring.series.auto.wiring;

public class Address {

	private String street;
	private String city;
	private String state;
	private String zipcode;

	/**
	 * getter's and setter's
	 */
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
	public String getZipcode() {
		return zipcode;
	}
	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}

	/**
	 * This method prints the address details
	 */
	public void printAddressDetail(){
		System.out.println("Address Street \t\t: " + street);
		System.out.println("Address City \t\t: " + city);
		System.out.println("Address State \t\t: " + state);
		System.out.println("Address Zip Code \t: " + zipcode);
	}
}

Employee class

Same here too, spring bean with four primitive properties and one complex property named “address” and its getter/setters with one public method called “printEmployeeDetail()” to print the employee details

Employee.java

package com.spring.series.auto.wiring;

public class Employee {

	private String name;
	private int age;
	private String employeeCode;
	private String designation;
	private Address address;

	/**
	 * getter's and setter's
	 */
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getEmployeeCode() {
		return employeeCode;
	}
	public void setEmployeeCode(String employeeCode) {
		this.employeeCode = employeeCode;
	}
	public String getDesignation() {
		return designation;
	}
	public void setDesignation(String designation) {
		this.designation = designation;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}

	/**
	 * This method prints the employee details
	 */
	public void printEmployeeDetail(){

		System.out.println("Employee Name \t\t: " + name);
		System.out.println("Employee Age \t\t: " + age);
		System.out.println("Employee Code \t\t: " + employeeCode);
		System.out.println("Employee Designation \t: " + designation);

		System.out.println("\nInvoking Address object & Printing Address details\n");

		// this loc invokes method of Address class & this object is injected during spring bean instantiation
		address.printAddressDetail();
	}
}

Create Spring Bean Configuration file (Spring XML)

This Spring configuration XML file is pretty straight forward, instead of supplying the external dependencies explicitly by bean wiring it autowires using ‘byType’ mode by inspecting data type of the property. If the bean with same (compatible) data type is found, then dependencies get resolved.  Otherwise dependent object gets a “null’ value.

Note: Autowiring works only for objects. For simple types i.e.; primitives values needs to be provided explicitly using the <property> element see here

SpringContext.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" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- employee bean definition goes here -->
	<bean id="employee" class="com.spring.series.auto.wiring.Employee"
		autowire="byType">
		<property name="name" value="Mark" />
		<property name="age" value="32" />
		<property name="employeeCode" value="E10910" />
		<property name="designation" value="Software Architect" />
	</bean>

	<!-- address bean definition goes here -->
	<bean id="addressBean" class="com.spring.series.auto.wiring.Address">
		<property name="street" value="Spring Office St." />
		<property name="city" value="Columbus" />
		<property name="state" value="OHIO" />
		<property name="zipcode" value="43211" />
	</bean>

</beans>

Note: Name of the Spring Bean Configuration file can be anything (not necessary to have SpringContext.xml) and it’s your choice. But, in the enterprise application keep these file names appropriate to the business context. So that it will increase the readability of the application.

Project Structure in Eclipse (Package Explorer view)

Autowiring_byType

Test the Application that’s exactly …. Run it!

Let’s test using ApplicationContext

TestEmployee.java

package com.spring.series.auto.wiring;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestEmployee {

	public static void main(String[] args) {
		testAutoWiring();
	}

	private static void testAutoWiring(){

		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/spring/series/auto/wiring/SpringContext.xml");
		Employee employee = (Employee) applicationContext.getBean("employee");

		System.out.println("Spring Autowiring using byType mode \n");

		// invoke print() method of Employee class
		employee.printEmployeeDetail();
	}
}

Output in console

Spring Autowiring using byType mode 

Employee Name 		: Mark
Employee Age 		: 32
Employee Code 		: E10910
Employee Designation 	: Software Architect

Invoking Address object & Printing Address details

Address Street 		: Spring Office St.
Address City 		: Columbus
Address State 		: OHIO
Address Zip Code 	: 43211

Be cautious, while configuring Spring context XML!!

If we have two beans with same data type and we set autowire=”byType”, then container finds difficult to resolves the dependencies as to which bean needs to be injected. And this ambiguity causes the container throw some fatal error. See below for details with coding

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- employee bean definition goes here -->
	<bean id="employee" class="com.spring.series.auto.wiring.Employee"
		autowire="byType">
		<property name="name" value="Mark" />
		<property name="age" value="32" />
		<property name="employeeCode" value="E10910" />
		<property name="designation" value="Software Architect" />
	</bean>

	<!-- address bean definition goes here -->
	<bean id="address" class="com.spring.series.auto.wiring.Address">
		<property name="street" value="Spring Office St." />
		<property name="city" value="Columbus" />
		<property name="state" value="OHIO" />
		<property name="zipcode" value="43211" />
	</bean>

	<bean id="addressBean" class="com.spring.series.auto.wiring.Address">
		<property name="street" value="Spring Office St." />
		<property name="city" value="Columbus" />
		<property name="state" value="OHIO" />
		<property name="zipcode" value="43211" />
	</bean>

</beans>

In the above configuration file, there are two beans with same data type with bean name “address” & “addressBean”. And we also set attribute autowire=”byType” in the employee <bean> element. At runtime while resolving collaborating beans, containers find difficult as to which one of these two beans needs to be injected and throws a “NoUniqueBeanDefinitionException” exception

See the complete error trace:

Aug 03, 2014 7:53:27 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@2cc24ae7: startup date [Sun Aug 03 19:53:27 IST 2014]; root of context hierarchy
Aug 03, 2014 7:53:27 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/spring/series/auto/wiring/SpringContext.xml]
Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'employee' defined in class path resource [com/spring/series/auto/wiring/SpringContext.xml]: Unsatisfied dependency expressed through bean property 'address': : No qualifying bean of type [com.spring.series.auto.wiring.Address] is defined: expected single matching bean but found 2: address,addressBean; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.spring.series.auto.wiring.Address] is defined: expected single matching bean but found 2: address,addressBean
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1278)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1170)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.spring.series.auto.wiring.TestEmployee.testAutoWiring(TestEmployee.java:14)
	at com.spring.series.auto.wiring.TestEmployee.main(TestEmployee.java:9)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.spring.series.auto.wiring.Address] is defined: expected single matching bean but found 2: address,addressBean
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:967)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:855)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByType(AbstractAutowireCapableBeanFactory.java:1263)
	... 14 more

In the next article, we will see an demonstration for autowiring using constructor

Download project

Spring Autowiring using byType (3kB)

Happy Coding !!
Happy Learning !!