Master java skills

Constructor injection

Dependencies can also be injected using constructors of the class. This is known as constructor injection. For this, <constructor-arg> element is used within the <bean> element. Follow the below example to understand it.

package com.sks;

public class Book {

	private int id;
	private String name;
	private String platform;

	//argument constructor

	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", platform=" + platform + "]";
	}

}

applicationContext.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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


	<bean id="book1" class="com.sks.Book">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Tomb of Sand"></constructor-arg>
		<constructor-arg type="String" value="Amazon"></constructor-arg>
	</bean>

	<bean id="book2" class="com.sks.Book">
		<constructor-arg type="int" value="102"></constructor-arg>
		<constructor-arg type="String"
			value="The God of Small Things"></constructor-arg>
		<constructor-arg type="String" value="Flipkart"></constructor-arg>
	</bean>

</beans>

Main testing class

package com.sks;

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

public class BookMain {

	public static void main(String[] args) {

		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

		Book b1 = (Book) context.getBean("book1");
		System.out.println("Book info : " + b1);

		Book b2 = (Book) context.getBean("book2");
		System.out.println("Book info : " + b2);
		
		((ClassPathXmlApplicationContext)context).close();

	}
}
Output :
Book info : Book [id=101, name=Tomb of Sand, platform=Amazon]
Book info : Book [id=102, name=The God of Small Things, platform=Flipkart]

Constructor injection for custom object

In this below example, we will create on Employee class which will have a dependency of Address class.

package com.sks;

public class Book {

	private int id;
	private String name;
	private Platform platform;

	//arg constructor
	//toString

}
package com.sks;

public class Platform {

	private int id;
	private String name;

	public Platform(int id, String name) {
		super();
		this.id = id;
		this.name = name;
	}

	@Override
	public String toString() {
		return "Platform [id=" + id + ", name=" + name + "]";
	}
}

applicationContext.xml

Please note that in the below xml file, Book bean is using contructor injection, whereas Platform bean is using setter injection. This is perfectly fine. However, Platform bean can also use constructor injection. Please refer the two ‘applicationContext.xml’ file.

<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


	<bean id="book1" class="com.sks.Book">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Tomb of Sand"></constructor-arg>
		<constructor-arg>
			<ref bean="platform1"/>
		</constructor-arg>
	</bean>
	
	<bean id="platform1" class="com.sks.Platform">
		<property name="id" value="101"></constructor-arg>
		<property name="name" value="Amazon"></constructor-arg>
	</bean>

</beans>
<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


	<bean id="book1" class="com.sks.Book">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Tomb of Sand"></constructor-arg>
		<constructor-arg>
			<ref bean="platform1"/>
		</constructor-arg>
	</bean>
	
	<bean id="platform1" class="com.sks.Platform">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Amazon"></constructor-arg>
	</bean>

</beans>

Main testing class

package com.sks;

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

public class BookMain {

	public static void main(String[] args) {

		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContextone.xml");

		Book b1 = (Book) context.getBean("book1");
		System.out.println("Book info : " + b1);

		((ClassPathXmlApplicationContext)context).close();
	}
}

Constructor injection with List

List can be mapped using constructor injection in the following way.

Assume the book sells on multiple platforms. So, we have a list of platforms.

package com.sks;

import java.util.List;

public class Book {

	private int id;
	private String name;
	private List<String> platforms;

	public Book(int id, String name, List<String> platforms) {
		super();
		this.id = id;
		this.name = name;
		this.platforms = platforms;
	}

	@Override
	public String toString() {
		return "Book [id=" + id + ", name=" + name + ", platforms=" + platforms + "]";
	}
}
<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


	<bean id="book1" class="com.sks.Book">
		<constructor-arg type="int" value="102"></constructor-arg>
		<constructor-arg type="String"
			value="The God of Small Things"></constructor-arg>
		<constructor-arg>
			<list>
				<value>Amazon</value>
				<value>Flipkart</value>
			</list>
		</constructor-arg>
	</bean>

</beans>

If list of platforms is a custom object list, then the mapping would be like below.

Platform.java class

package com.sks;

public class Platform {

	private int id;
	private String name;

	//constructor
	//toString
}
<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">


	<bean id="book1" class="com.sks.Book">
		<constructor-arg type="int" value="102"></constructor-arg>
		<constructor-arg type="String"
			value="The God of Small Things"></constructor-arg>
		<constructor-arg>
			<list>
				<ref bean="platform1"/>
				<ref bean="platform2"/>
			</list>
		</constructor-arg>
	</bean>
	
	<bean id="platform1" class="com.sks.Platform">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Amazon"></constructor-arg>
	</bean>
	
	<bean id="platform2" class="com.sks.Platform">
		<constructor-arg type="int" value="101"></constructor-arg>
		<constructor-arg type="String" value="Flipkart"></constructor-arg>
	</bean>

</beans>

Constructor Injection with Map

package com.sks;

import java.util.HashMap;
import java.util.Map;

public class Employee {
	
	private int id;
	private String name;
	private int age;
	private boolean contract;
	private Map<Integer, String> projectsMap = new HashMap<Integer, String>();
	
	public Employee(int id, String name, int age, boolean contract, Map<Integer, String> projectsMap) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
		this.contract = contract;
		this.projectsMap = projectsMap;
	}
	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", contract=" + contract + ", projectsMap="
				+ projectsMap + "]";
	}
}
<?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:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans  
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

	<bean id="emp" class="com.sks.Employee">
		<constructor-arg type="int" value="100"></constructor-arg>
		<constructor-arg type="String" value="Mark Taylor"></constructor-arg>
		<constructor-arg type="int" value="30"></constructor-arg>
		<constructor-arg type="boolean" value="false"></constructor-arg>
		<constructor-arg>
			<map>
			 	<entry key="1" value="Project1"/>
				<entry key="2" value="Project2"/>
				<entry key="3" value="Project3"/>
			</map>
		</constructor-arg>
	</bean>
</beans>

Tesing main class

package com.sks;

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

public class EmployeeMain {

	public static void main(String[] args) {
		
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		
		Employee e = (Employee) context.getBean("emp");
		
		System.out.println("e1 bean information is : " + e);
		
		((ClassPathXmlApplicationContext) context).close();
		
	}
}
Output :
e1 bean information is : Employee [id=100, name=Mark Taylor, age=30, contract=false, projectsMap={1=Project1, 2=Project2, 3=Project3}]