Dependency injection in Spring
Dependency injection is an advanced topic.
The term was coined by Martin Fowler in 2004 to describe the new, novel and almost magical way that inversion of control containers initialized the properties of the objects they managed.
IoC frameworks of the day, such as Spring and the Pico container, had achieved loose coupling in a remarkably unobtrusive way, and tech leaders in the community knew this quickly emerging pattern needed its own name.
"With a lot of discussion with various IoC advocates we settled on the name dependency injection," said Martin Fowler in a 2004 blog that explained the rationale for the new pattern.
Spring's dependency injection made easy
According to Fowler, the following criteria are required to realize true dependency injection:
- An inversion of control container that manages objects.
- Managed objects that have dependencies upon each other.
- A convention, such as annotations or XML files, that describes how to satisfy dependencies.
When an IoC framework uses externalized configuration data to resolve dependencies between components, dependency injection occurs.
Dependency injection example in Spring
Let's look at a dependency injection example that uses Spring as the IoC framework, and annotations as the convention that provides the container hints on how to resolve dependencies at runtime.
For the objects our IoC container will manage, let's model an old-school Atari gaming console, the one where you insert a game cartridge into the console before you turn it on. We can say our Atari game console is dependent upon a game cartridge in order to work.
The code would look like this:
class GameCartridge {
void welcomeMessage(){
System.out.print("Would you like to play a game?");
}
}
class AtariGameConsole {
@Autowired
GameCartridge game;
AtariGameConsole(GameCartridge game) {
this.game = game;
}
void splashScreen() {
game.welcomeMessage();
}
}
Autowired Spring dependencies
The GameCartridge
class in the AtariGameConsole
class is decorated with an @Autowired
annotation. This tells Spring to find an instance of a GameCartridge
class at runtime and provide it to the AtariGameConsole
.
The code to run the application is as follows:
var spring = new AnnotationConfigApplicationContext(AtariGameConsole.class, GameCartride.class);
var gameConsole = spring.getBean(AtariGameConsole.class);
gameConsole.splashScreen();
What is dependency injection?
According to Fowler, who is credited with inventing the term, dependency injection describes the unique manner in which an IoC container achieves loose coupling, by unobtrusively initializing the properties of the objects it manages.
That's a good description of what the Spring IoC container does.
Through XML configuration files, annotations and potentially even Java-based guidance, the Spring Framework lets developers concentrate solely on the business logic required to get their components to work, and the resolution of dependencies and the wiring of components can be managed separately from their code.
All of that makes development faster, testing easier and the software development lifecycle go a little smoother.
Cameron McKenzie has been a Java EE software engineer for 20 years. His current specialties include Agile development; DevOps; Spring; and container-based technologies such as Docker, Swarm and Kubernetes.