Spring dependency injection example
Used software and configuration
This tutorial considers the following software and environment:
- Ubuntu 12.04
- Maven 3.0.4
- JDK 1.7.0.09
- Spring 3.2.0
Configure Maven to get the required Spring dependencies:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.byteslounge.spring</groupId> <artifactId>com-byteslounge-spring</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>com-byteslounge-spring</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <!-- Define Spring version as a constant --> <spring.version>3.2.0.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> </dependencies> </project>
Now place yourself in the project directory and issue the following command to prepare your project for Eclipse:
After conclusion you can import the project into Eclipse.
Spring dependency injection overview
One of most powerful Spring features is the Dependency Injection (DI) or otherwise called Inversion of Control (IoC) mechanism. The Spring container is capable of fetching a managed bean and inject that bean into another managed bean. Usually the application developer defines a Java interface and then declares a property in a managed bean which type is the same of that interface. When the Spring container initializes the bean it will automatically fetch an implementation of that interface and inject into the bean, i.e. the bean has a dependency that is injected during initialization time. This way the target bean becomes completely decoupled from the bean that is injected, i.e. the implementation of the interface can be switched by another implementation without changing any single piece of code in the target bean. The interface implementation itself must also be a Spring managed bean, but let's see it in practice.
Preparing the injected bean
First we define the interface of the injected bean:
package com.byteslounge.spring; public interface InjectedBean { void doSomething(); }
Now we define the implementation:
package com.byteslounge.spring; import org.springframework.stereotype.Service; @Service public class InjectedBeanImpl implements InjectedBean { @Override public void doSomething() { System.out.println("Bean was correctly injected!"); } }
Note the @Service annotation. This tells the Spring container that this class is a managed bean. When the Spring container scans this package for beans during container initialization it will know that this class represents a managed bean.
Defining the target bean
Now we define a simple Spring bean that will receive the injected bean as a dependency:
package com.byteslounge.spring; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class ExampleBean { @Autowired private InjectedBean injectedBean; public void callExampleMethod() { injectedBean.doSomething(); } }
Note the injectedBean bean property defined as InjectedBean type. The used type here is the interface type. We should also note that this property is annotated with @Autowired annotation. This means that when the Spring container initializes this bean it will lookup for an implementation of this interface type and inject it as a property of this bean! This is actually the Spring Dependency Injection mechanism. You can easily see that the injected bean and the target bean became decoupled. You can switch the injected bean implementation without changing a single line of code in the target bean.
The Main application class
Our Main class looks like the following:
package com.byteslounge.spring; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main( String[] args ) { ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); ExampleBean exampleBean = (ExampleBean) ctx.getBean("exampleBean"); exampleBean.callExampleMethod(); } }
As we have already seen in previous Spring tutorials on this website we are simply initializing the Spring container from spring.xml configuration file. Then we fetch exampleBean bean from the container and call its callExampleMethod() method.
Spring configuration
For this example we need to define the packages where the Spring container should look for beans (the classes annotated with @Service annotation from the previous tutorial sections):
<?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:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <context:component-scan base-package="com.byteslounge.spring" /> </beans>
Running the application
When we run the application the following output will be generated:
InjectedBean was injected into ExampleBean and doSomething() method from the injected bean was successfully called. This tutorial's source code is available for download at the bottom of this page.