How do I inject collections using list element in Spring?

The following example show you how to use the <list> element to wire collections property. We can use it to wire property of either arrays or some implementation of java.util.Collection such as java.util.ArrayList.

For this example we will create a bean called Album that have a collection of Song beans in it. So here is our bean classes.

package org.kodejava.example.spring.collection;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class Album {
    private String title;
    private int year;
    private List<Song> songs = new ArrayList<>();
    private Map<String, Publisher> publisher = new HashMap<>();
    private Properties props = new Properties();

    public Album() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public void setSongs(List<Song> songs) {
        this.songs = songs;
    }

    public void setPublisher(Map<String, Publisher> publisher) {
        this.publisher = publisher;
    }

    public void setProps(Properties props) {
        this.props = props;
    }

    @Override
    public String toString() {
        return "Album{" +
            "title='" + title + '\'' +
            ", year=" + year +
            ", songs=" + songs +
            ", publisher=" + publisher +
            ", props=" + props +
            '}';
    }
}
package org.kodejava.example.spring.collection;

public class Song {
    private String title;
    private String writer;

    public Song() {
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    @Override
    public String toString() {
        return "Song{" +
            "title='" + title + '\'' +
            ", writer='" + writer + '\'' +
            '}';
    }
}
package org.kodejava.example.spring.collection;

public class Publisher {
    private String name;

    public Publisher() {
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Publisher{" +
                "name=" + name +
                '}';
    }
}

Here is the Spring configuration file, CollectionList.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="song1" class="org.kodejava.example.spring.collection.Song">
        <property name="title" value="I Saw Her Standing There" />
        <property name="writer" value="Beatles" />
    </bean>

    <bean id="song2" class="org.kodejava.example.spring.collection.Song">
        <property name="title" value="Misery" />
        <property name="writer" value="Beatles" />
    </bean>

    <bean id="song3" class="org.kodejava.example.spring.collection.Song">
        <property name="title" value="Anna (Go to Him)" />
        <property name="writer" value="Beatles" />
    </bean>


    <bean id="album" class="org.kodejava.example.spring.collection.Album">
        <property name="title" value="Please Please Me"/>
        <property name="year" value="1963"/>
        <property name="songs">
            <list>
                <ref bean="song1"/>
                <ref bean="song2"/>
                <ref bean="song3"/>
            </list>
        </property>
    </bean>

</beans>

The part of the configuration that wire the songs collection is inside the album bean. You can see that we have a property name songs. This property have a <list> element that contains a couple <ref> elements referring to some Song type beans.

Now let’s run it with the following code:

package org.kodejava.example.spring.collection;

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

public class DemoList {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
            new String[]{"collection-list.xml"});

        Album album = (Album) context.getBean("album");
        System.out.println("Album = " + album);
    }
}

You’ll see the following output when you run the program:

Album = Album{title='Please Please Me', year=1963, songs=[Song{title='I Saw Her Standing There', writer='Beatles'}, Song{title='Misery', writer='Beatles'}, Song{title='Anna (Go to Him)', writer='Beatles'}], publisher={}, props={}}

How do I inject collections properties in Spring?

Beside injecting a simple value (using the value attribute) and a reference to other bean (using the ref attribute). We can also inject collections properties into a bean.

Spring provides four ways to inject collections. There are <list> and <set> that can be used to inject arrays or any implementation of java.util.Collection. The <map> that can be used to inject property of type java.util.Map. And the <props> can be used to inject property of type java.util.Properties.

Here is a table that summarize the collection configuration support in Spring.

Collection Element Description
<list> Wiring a list of values, where the values might have duplicates.
<set> Wiring a set of values, where the values can not have duplicates.
<map> Wiring a key-value pairs collection, where the key and value can be any type
<props> Wiring a key-value pairs property, where the key and value are both type of String

You can see the following example on how to use each type of this collection configuration:

How do I wire properties with Spring’s p namespace?

Beside using the <property> element, Spring framework also provide us another way to wiring value or reference into the bean. We can use the Spring’s p namespaces. The p namespace has a schema URI of http://www.springframework.org/schema/p.

With this namespace declared in the Spring configuration file you can use the p: prefixed attribute of the <bean> element to wire bean’s property.

We update the configuration used in the previous example How do I inject into bean properties? to use the p namespace. Here is the new Spring’s configuration 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.xsd">

    <bean id="rectangle" class="org.kodejava.example.spring.inject.Rectangle"/>

    <bean id="drawingBean"
          class="org.kodejava.example.spring.inject.DrawingBean"
          p:colour="Red" p:shape-ref="rectangle"/>

</beans>

The p:color attribute set the color property to Red, this is a simple value. To set the shape property we use the p:shape-ref attribute. The -ref suffix tell Spring that we are injecting a reference.

You can use the <property> element or using the p namespace to inject bean’s property. Both of them have the same functionality.

How do I define inner bean in Spring?

Inner bean is a bean define inside another bean, it can be seen as an inner class. In another word the inner bean is a bean defined within the scope of another bean. In this case the inner bean can only be use by the outer bean. No other bean in the Spring context can refer to that bean.

So if you sure that a bean is only use within a single bean it is a good idea to use an inner bean instead. Inner bean can be injected through setter injection or constructor injection.

Here is an example of Spring configuration for an inner bean injection:

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="racer" class="org.kodejava.example.spring.innerbean.Racer">
        <property name="car">
            <bean class="org.kodejava.example.spring.innerbean.Car">
                <property name="maker" value="Ferrari"/>
                <property name="year" value="2019"/>
            </bean>
        </property>
    </bean>

</beans>

In this configuration we use a setter injection. So we use the property element. Instead of using a ref attribute for referring to another bean we define the bean using the bean element inside the property element. And then we create the Car bean and sets its properties.

If you want to you a constructor injection you can inject the Car bean into the Racer bean by defining a bean inside of the constructor-arg element in the Racer bean.

Below is our Racer and Car classes.

package org.kodejava.example.spring.innerbean;

public class Racer {
    private Car car;

    public Racer() {
    }

    public Racer(Car car) {
        this.car = car;
    }

    public void setCar(Car car) {
        this.car = car;
    }

    @Override
    public String toString() {
        return "Racer{" +
            "car=" + car +
            '}';
    }
}
package org.kodejava.example.spring.innerbean;

public class Car {
    private String maker;
    private int year;

    public void setMaker(String maker) {
        this.maker = maker;
    }

    public void setYear(int year) {
        this.year = year;
    }

    @Override
    public String toString() {
        return "Car{" +
            "maker='" + maker + "'" +
            ", year=" + year +
            '}';
    }
}

Let’s create our Demo class to run the program:

package org.kodejava.example.spring.innerbean;

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

public class Demo {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
            new String[]{"inner-bean.xml"});

        Racer racer = (Racer) context.getBean("racer");
        System.out.println("Racer = " + racer);
    }
}

Here is the output of our program:

Racer = Racer{car=Car{maker='Ferrari', year=2019}}

How do I inject into bean properties?

A bean usually have some private properties that can be accessed through a pair of accessor methods, the setters and getters. This setters, the setXXX() method can be used by Spring framework to configure the beans.

This method of injecting beans property through their setter methods is called the setter injection. The following example will show you how to do it.

Below is our DrawingBean that have colour and shape properties. In the example we will inject both of the properties using their respective setter method. This configuration is done in the Spring application configuration file.

package org.kodejava.example.spring.inject;

public class DrawingBean {
    private String colour;
    private Shape shape;

    public DrawingBean() {
    }

    public void drawShape() {
        getShape().draw();
        System.out.printf("The colour is %s.", getColour());
    }

    public String getColour() {
        return colour;
    }

    public void setColour(String colour) {
        this.colour = colour;
    }

    public Shape getShape() {
        return shape;
    }

    public void setShape(Shape shape) {
        this.shape = shape;
    }
}

We can inject a simple value into a bean, such as string, number, etc. We can also inject a reference to another bean. Here we define an example of other bean, the Rectangle bean that we will inject into the DrawingBean.

package org.kodejava.example.spring.inject;

public interface Shape {
    /**
     * Draw a shape.
     */
    void draw();
}
package org.kodejava.example.spring.inject;

public class Rectangle implements Shape {
    @Override
    public void draw() {
        System.out.println("Drawing a rectangle.");
    }
}

Let’s create the Spring application configuration file that will register our beans into the Spring context. After that we just create a simple program to execute it.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="rectangle" class="org.kodejava.example.spring.inject.Rectangle"/>

    <bean id="drawingBean" class="org.kodejava.example.spring.inject.DrawingBean">
        <property name="colour" value="Red"/>
        <property name="shape" ref="rectangle"/>
    </bean>

</beans>

In the configuration file above you can see that we use the property element to set a bean’s property. The name attribute is referring to the bean’s setter methods name, exclude the set prefix.

The value attribute of the property element is used to inject a simple value, such as string, int, etc. For injecting a reference to another bean we use the ref attribute instead.

package org.kodejava.example.spring.inject;

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

public class DrawingBeanDemo {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
            new String[]{"drawing-bean.xml"});
        DrawingBean bean = (DrawingBean) context.getBean("drawingBean");
        bean.drawShape();
    }
}

Here are the output of our example:

Drawing a rectangle.
The colour is Red.

How do I defaulting init-method and destroy method in Spring?

When many beans in a context definition will have the same initialization and destroy method name, you can define a default-init-method and default-destroy-method in the attributes of the beans element.

This way you don’t have to define individual init-method and destroy-method for each of your beans. When the beans does not supply the method that match the name of defined default-init-method or default-destroy-method nothing will happen to those beans.

Let’s see an example code below. Firs here is our simple bean, the AutoEngine bean.

package org.kodejava.example.spring.init;

public class AutoEngine {
    public void initialize() {
        System.out.println("AutoEngine.initialize");
    }

    public void destroy() {
        System.out.println("AutoEngine.destroy");
    }
}

And then we define our Spring configuration file. You can see that there are default-init-method and default-destroy-method in the attribute of the beans element.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd"
       default-init-method="initialize" default-destroy-method="destroy">

    <bean id="engine" class="org.kodejava.example.spring.init.AutoEngine"/>

</beans>

And finally a small program to run our demo.

package org.kodejava.example.spring.init;

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

public class DefaultInitDestroyDemo {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new ClassPathXmlApplicationContext("default-init-destroy.xml");

        AutoEngine engine = (AutoEngine) context.getBean("engine");

        // context.close will remove the bean from the container.
        // This will call our bean destroy method.
        context.close();
    }
}

When you run this example you’ll get the following output printed on your screen:

AutoEngine.initialize
AutoEngine.destroy

How do I use InitializingBean and DisposableBean interfaces in Spring?

In the other example, How do I initialize and destroy beans in Spring? you can see how to initializing and destroying a bean using the Spring configuration init-method and destroy-method.

In the following example you’ll see how to achieve the same thing using the Spring API. In this case our class need to implements the InitializingBean and DisposableBean. These interfaces is located under the org.springframework.beans.factory package.

The InitializingBean interface requires us to implements the afterPropertiesSet() method. This method will be the init method of our bean. The destroy() method which is a contract defined in the DisposableBean interface is where we’ll place the clean-up logic of our bean.

The drawback of using this approach is that our classes will be required to use the Spring API. If you want to use the class outside the Spring container using the other approach mentioned above is a better way to go.

Now, let’s see some code in action.

package org.kodejava.example.spring.destroy;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class InitDisposeService implements InitializingBean, DisposableBean {

    /**
     * Do some processes.
     */
    public void doSomething() {
        System.out.println("InitDisposeService.doSomething");
    }

    /**
     * Initialize bean after property set.
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitDisposeService.afterPropertiesSet");
    }

    /**
     * Clean-up bean when the context is closed.
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("InitDisposeService.destroy");
    }
}

As usual, we define our Spring configuration (init-dispose.xml) to register our bean. In this case we will create a bean with id called service and will be using the InitDisposeService class.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="service" class="org.kodejava.example.spring.destroy.InitDisposeService"/>

</beans>

Below is a small Java program that we can use to run our application. This will load the Spring configuration, get the bean from the container and execute the bean. We’ll see that the afterPropertiesSet method is called. And when the context is closed the destroy method is also executed.

package org.kodejava.example.spring.destroy;

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

public class InitDisposeDemo {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
            new ClassPathXmlApplicationContext("init-dispose.xml");

        InitDisposeService service =
            (InitDisposeService) context.getBean("service");
        service.doSomething();

        context.close();
    }
}

Here are the output printed on the screen:

InitDisposeService.afterPropertiesSet
InitDisposeService.doSomething
InitDisposeService.destroy

How do I initialize and destroy beans in Spring?

When creating an instance of a bean you might need to do some initialization to the bean. Likewise, when the bean is no longer needed and removed from the Spring container you might want to do some cleanup routine or destroy the bean.

To do this initialization and destroy routine you can use the init-method and destroy-method attribute when declaring a bean in spring configuration using the <bean> element.

By defining the init-method and destroy-method it will allow the Spring Container to call the initialization method right after the bean created. And just before the bean removed and discarded from the container, the defined destroy method will be called. Let’s see some code snippet as an example.

package org.kodejava.example.spring.init;

public class AutoEngine {
    public void initialize() {
        System.out.println("AutoEngine.initialize");
    }

    public void destroy() {
        System.out.println("AutoEngine.destroy");
    }
}

Below is the Spring configuration file that we use to declare the bean. You’ll see in the configuration there are additional attributes that we add to the bean.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="engine" class="org.kodejava.example.spring.init.AutoEngine"
          init-method="initialize" destroy-method="destroy"/>

</beans>

Create a small program to execute our demo:

package org.kodejava.example.spring.init;

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

public class InitDestroyDemo {
    public static void main(String[] args) {
        ConfigurableApplicationContext context =
                new ClassPathXmlApplicationContext("init-destroy.xml");

        AutoEngine engine = (AutoEngine) context.getBean("engine");

        // context.close will remove the bean from the container. 
        // This will call our bean destroy method.
        context.close();
    }
}

When you run the program it will print the following output:

AutoEngine.initialize
AutoEngine.destroy

The advantage of using this method to initialize or clean up the bean is that it does not mandate our bean to implement or extend any Spring API which will make our bean reusable on other container beside Spring.

How do I define bean scoping in Spring?

Bean scoping is how the bean is created and returned from the spring container to the bean requester. By default the scope of all bean is singleton. The spring container will always return the same bean whenever this bean is required, for instance when in injected or call using the getBean() method from the application context.

There are five types of bean scope define in the Spring Container:

Scope Description
singleton Scope the bean definition to a single bean instance per Spring Container. This is the default scope when no scope is defined when creating a bean.
prototype Scope the bean to allow multiple times bean creation. This will create a new bean for each time the bean is required.
request Scope the bean definition to a single HTTP request. *
session Scope the bean definition to a single HTTP session. *
global-session Scope the bean definition to a global HTTP session. *

*) This is only valid when using the web-capable Spring context.

Let’s see the difference between Singleton and Prototype scope. First we’ll create our DummyService class.

package org.kodejava.example.spring.dummy;

public class DummyService {
    private String message;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

Singleton Scope

By default when no scope defined it will be a singleton.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="service" class="org.kodejava.example.spring.dummy.DummyService"/>

</beans>

Now create a program to run our example. First will run it using the singleton.xml as the configuration.

package org.kodejava.example.spring.dummy;

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

public class BeanScopeDemo {
    public static void main(String[] args) {
        ApplicationContext context =
            new ClassPathXmlApplicationContext("singleton.xml");

        DummyService serviceA =
            (DummyService) context.getBean("service");
        serviceA.setMessage("Hello From A");
        System.out.println("Message A = " + serviceA.getMessage());

        DummyService serviceB =
            (DummyService) context.getBean("service");
        System.out.println("Message B = " + serviceB.getMessage());
    }
}

The output of the singleton configuration is:

Message A = Hello From A
Message B = Hello From A

The above output show that the message printed by the serviceB is the same as the serviceA. We don’t even set the message in the serviceB explicitly. It print the same message because the getBean() method actually return the same bean both for serviceA and serviceB. This is the singleton scope.

Prototype Scope

To change the scope to prototype use the scope attribute in the bean element as shown below.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

    <bean id="service" class="org.kodejava.example.spring.dummy.DummyService"
          scope="prototype"/>

</beans>
package org.kodejava.example.spring.dummy;

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

public class BeanScopePrototypeDemo {
    public static void main(String[] args) {
        ApplicationContext context =
            new ClassPathXmlApplicationContext("prototype.xml");

        DummyService serviceA =
            (DummyService) context.getBean("service");
        serviceA.setMessage("Hello From A");
        System.out.println("Message A = " + serviceA.getMessage());

        DummyService serviceB =
            (DummyService) context.getBean("service");
        System.out.println("Message B = " + serviceB.getMessage());
    }
}

Now if you try to run the same program again but changing the configuration to prototype.xml you’ll get the following output printed:

Message A = Hello From A
Message B = null

The serviceB now print a different message. This is the effect of using the prototype scope. When we call the getBean() a new bean will be created per request.

How do I create beans through factory method?

This example show you how to create a bean using factory method in Spring Framework. We will use a singleton as an example. An instance of a singleton can be obtained only from a factory method because a singleton will have a private constructor so it will not possible to create an instance of this class from outside the singleton itself.

Here is our singleton bean will look like. To get an instance of it we well need to call the getInstance() method.

package org.kodejava.example.spring.factory;

public class Singleton {

    /**
     * Private constructor.
     */
    private Singleton() {
    }

    private static class SingletonHolder {
        static Singleton instance = new Singleton();
    }

    /**
     * Get an instance of Singleton class.
     * @return an instance of Singleton class.
     */
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }

    /**
     * Do something.
     */
    public void doSomething() {
        System.out.println("Singleton.doSomething");
    }
}

Next, we will create a spring configuration file. At it simplest a bean in the configuration file will have an id and a class. To tell the spring container to create the bean using a factory method we must use the factory-method attribute of the bean element.

Here is our configuration file and we name it factory-method.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="singleton" class="org.kodejava.example.spring.factory.Singleton"
          factory-method="getInstance">
    </bean>

</beans>

Let’s now run our program below:

package org.kodejava.example.spring;

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

public class FactoryMethodDemo {
    public static void main(String[] args) {
        ApplicationContext context =
                new ClassPathXmlApplicationContext("factory-method.xml");

        Singleton instance =
                (Singleton) context.getBean("singleton");
        instance.doSomething();
    }
}