This article describes how to use dependency injection with the Spring Framework. It first describes dependency injection as a general principle, gives then an overview of Spring and explains the configuration of Spring with annotations and with XML.

1. Dependency Injection in Spring

The fundamental functionality provided by the Spring framework is the support for dependency injection (DI) and the management of the objects which can be injected.

Dependency injection (DI) is a design principle to makes your application:

  • easier to develop

  • your code less coupled

  • easier to test your code

Spring provides a light-weight container, e.g. the Spring core container, for DI. The injection in Spring is either done via setter injection of via construction injection. These classes which are managed by Spring must conform to the JavaBean standard. In the context of Spring classes are also referred to as beans or as Spring beans.

The Spring core container:

  • handles the configuration, generally based on annotations or on an XML file (XMLBeanFactory)

  • manages the selected Java classes via the BeanFactory

The core container uses the so-called bean factory to create new objects. New objects are generally created as Singletons if not specified differently.

The injection in Spring is either done via setter, field or constructor injection. Classes which are managed by Spring DI must conform to the Java bean standard.

In the context of Spring classes are also referred to as beans or as spring beans.

2. Exercise - Use dependency injection in a Spring based application

In this small exercise you use the Spring Tools Suite (STS) to create a small Spring Boot project. You create a small data model and use the Spring DI framework to construct these objects.

2.1. Create project

Create a new Spring Starter project called com.vogella.spring.di.model with Gradle as build tool. No additional project dependencies are necessary for this example.

2.2. Create data model

Create the following packages and classes.

package com.vogella.spring.di.model;

public interface IWriter {
    void writer(String s);
}
package com.vogella.spring.di.model;

public class Writer implements IWriter {
    @Override
    public void writer (String s){
        System.out.println(s);
    }
}
package com.vogella.spring.di.model;

public class NiceWriter implements IWriter {
    @Override
    public void writer (String s){
        System.out.println("The string is " + s);
    }
}
package com.vogella.spring.di.model;

public class MySpringBeanWithDependency {
    private IWriter writer;

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

    public void run() {
        String s = "This is my test";
        writer.writer(s);
    }
}

The class MySpringBeanWithDependency contains a setter for the actual writer. We will use the Spring Framework to inject the correct writer into this class.

2.3. Using dependency injection with annotations

Add the @Service annotation the MySpringBeanWithDependency and NiceWriter. Also define with @Autowired on the setWriter method that the property "writer" will be autowired by Spring.

@Autowired will tell Spring to search for a Spring bean which implements the required interface and place it automatically into the setter.
package testbean;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import writer.IWriter;

@Service
public class MySpringBeanWithDependency {
    private IWriter writer;

    @Autowired
    public void setWriter(IWriter writer) {
        this.writer = writer;
    }

    public void run() {
        String s = "This is my test";
        writer.writer(s);
    }
}
package writer;

import org.springframework.stereotype.Service;

@Service
public class NiceWriter implements IWriter {
    public void writer(String s) {
        System.out.println("The string is " + s);
    }
}

2.4. Update your application

Create the following configuration class.

package com.vogella.spring.di.model;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = { "com.vogella.spring.di.model" })
public class Config {
}

Change your application to "only" trigger dependency injection instead of starting a full Spring Boot application.

package com.vogella.spring.di.model;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Application {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        MySpringBeanWithDependency springBean = context.getBean(MySpringBeanWithDependency.class);
        springBean.run();
        context.close();
    }
}

2.5. Validate your change

Select your Application class, right mouse click on it and select Run-as  Java application. You should see the output in the Console.

The string is This is my test

2.6. Summary

This tutorial demonstrated how you can use Spring dependency injection to create and manage objects.

3. Links and Literature