Creating Beans by Invoking a Constructor

Suppose you are going to develop a shop application to sell products online. First of all, you create the Product class, which has several properties, such as the product name and price. As there are many types of products in your shop, you make the Product class abstract for different product subclasses to extend.

package com.shop;
public abstract class Product {
private String name;
private double price;
public Product() {}
public Product(String name, double price) {
this.name = name;
this.price = price;
}
// Getters and Setters
public String toString() {
return name + " " + price;
}
}

Then you create two product subclasses, Battery and Disc. Each of them has its own properties.

package com.shop;
public class Battery extends Product {
private boolean rechargeable;
public Battery() {
super();
}
public Battery(String name, double price) {
super(name, price);
}
// Getters and Setters
}
package com.shop;
public class Disc extends Product {
private int capacity;
public Disc() {
super();
}
public Disc(String name, double price) {
super(name, price);
}
// Getters and Setters
}

To define some products in the Spring IoC container, you create the following bean configuration file:

<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-2.5.xsd">
<bean id="aaa" class="com.shop.Battery">
<property name="name" value="AAA" />
<property name="price" value="2.5" />
<property name="rechargeable" value="true" />
</bean>
<bean id="cdrw" class="com.shop.Disc">
<property name="name" value="CD-RW" />
<property name="price" value="1.5" />
<property name="capacity" value="700" />
</bean>
</beans>

If there’s no <constructor-arg> element specified, the default constructor with no argument will be invoked. Then for each <property> element, Spring will inject the value through the setter method. The preceding bean configuration is equivalent to the following code snippet:

Product aaa = new Battery();
aaa.setName("AAA");
aaa.setPrice(2.5);
aaa.setRechargeable(true);
Product cdrw = new Disc();
cdrw.setName("CD-RW");
cdrw.setPrice(1.5);
cdrw.setCapacity(700);

Otherwise, if there are one or more <constructor-arg> elements specified, Spring will invoke the most appropriate constructor that matches your arguments.

<beans …>
<bean id="aaa" class="com.shop.Battery">
<constructor-arg value="AAA" />
<constructor-arg value="2.5" />
<property name="rechargeable" value="true" />
</bean>
<bean id="cdrw" class="com.shop.Disc">
<constructor-arg value="CD-RW" />
<constructor-arg value="1.5" />
<property name="capacity" value="700" />
</bean>
</beans>

As there is no constructor ambiguity for the Product class and subclasses, the preceding bean configuration is equivalent to the following code snippet:

Product aaa = new Battery("AAA", 2.5);
aaa.setRechargeable(true);
Product cdrw = new Disc("CD-RW", 1.5);
cdrw.setCapacity(700);

You can write the following Main class to test your products by retrieving them from the Spring IoC container:

package com.shop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) throws Exception {
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml");
Product aaa = (Product) context.getBean("aaa");
Product cdrw = (Product) context.getBean("cdrw");
System.out.println(aaa);
System.out.println(cdrw);
}
}