1.1. What is dependency injection?
Dependency injection is a concept valid for any programming language. The general concept behind dependency injection is called Inversion of Control. According to this concept a class should not configure its dependencies statically but should be configured from the outside.
A Java class has a dependency on another class, if it uses an instance of this class. We call this a _class dependency. For example, a class which accesses a logger service has a dependency on this service class.
Ideally Java classes should be as independent as possible from other Java classes. This increases the possibility of reusing these classes and to be able to test them independently from other classes.
If the Java class creates an instance of another class via the
new
operator, it cannot be used (and tested) independently from this class and this is called a hard dependency. The following example shows a class which has no hard dependencies.package com.vogella.tasks.ui.parts;
import java.util.logging.Logger;
public class MyClass {
private Logger logger;
public MyClass(Logger logger) {
this.logger = logger;
// write an info log message
logger.info("This is a log message.")
}
}
Please note that this class is just a normal Java class, there is nothing special about it, except that it avoids direct object creation. |
A framework class, usually called the dependency container, could analyze the dependencies of this class. With this analysis it is able to create an instance of the class and inject the objects into the defined dependencies, via Java reflection.
This way the Java class has no hard dependencies, which means it does not rely on an instance of a certain class. This allows you to testyour class in isolation, for example by using mock objects.
Mock objects (mocks) are objects which behave similar as the real object. But these mocks are not programmed; they are configured to behave in a certain predefined way. Mock is an English word which means to mimic or to imitate.
If dependency injection is used, a Java class can be tested in isolation.
1.2. Using annotations to describe class dependencies
Different approaches exist to describe the dependencies of a class. The most common approach is to use Java annotations to describe the dependencies directly in the class.
The standard Java annotations for describing the dependencies of a class are defined in the Java Specification Request 330 (JSR330). This specification describes the
@Inject
and @Named
annotations.
The following listing shows a class which uses annotations to describe its dependencies.
// import statements left out
public class MyPart {
@Inject private Logger logger;
// inject class for database access
@Inject private DatabaseAccessClass dao;
@Inject
public void createControls(Composite parent) {
logger.info("UI will start to build");
Label label = new Label(parent, SWT.NONE);
label.setText("Eclipse 4");
Text text = new Text(parent, SWT.NONE);
text.setText(dao.getNumber());
}
}
Please note that this class uses the new operator for the user interface components. This implies that this part of the code is nothing you plan to replace via your tests. In this case you made the decision to have a hard coupling to the corresponding user interface toolkit. |
1.3. Where can objects be injected into a class according to JSR330?
Dependency injection can be performed on:
- the constructor of the class (construction injection)
- a field (field injection)
- the parameters of a method (method injection)
It is possible to use dependency injection on static and on non-static fields and methods. Avoiding dependency injection on static fields and methods is a good practice, as it has the following restrictions and can be hard to debug.
- Static fields will be injected after the first object of the class was created via DI, which means no access to the static field in the constructor
- Static fields can not be marked as final, otherwise the compiler or the application complains at runtime about them
- Static methods are called only once after the first instance of the class was created
1.4. Order in which dependency injection is performed on a class
According to JSR330 the injection is done in the following order:
- constructor injection
- field injection
- method injection
The order in which the methods or fields annotated with
@Inject
are called is not defined by JSR330. You cannot assume that the methods or fields are called in the order of their declaration in the class.As fields and method parameters are injected after the constructor is called, you cannot use injected member variables in the constructor. |
2. Java and dependency injection frameworks
You can use dependency injection without any additional framework by providing classes with sufficient constructors or getter and setter methods.
A dependency injection framework simplifies the initialization of the classes with the correct objects.
Two popular dependency injection frameworks are Spring and Google Guice.
The usage of the Spring framework for dependency injection is described in Dependency Injection with the Spring Framework - Tutorial.
Also Eclipse 4 is using dependency injection.
2. Spring Overview
The Spring Framework is a very comprehensive framework. The fundamental functionality provided by the Spring Container is dependency injection. Spring provides a light-weight container, e.g. the Spring core container, for dependency injection (DI). This container lets you inject required objects into other objects. This results in a design in which the Java class are not hard-coupled. 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.
3. Spring Installation
Download Spring from http://www.springframework.org/download. Select the -with-dependencies.zip to get also all required plugins. At the time of writing I downloaded the version Spring Framework 2.5.5.
The folder "dist" contains the Spring container "spring.jar". The folder lib contains additional require libraries. A minimal Spring application requires the spring.jar, commons-logging.jar (from \lib\jakarta-commons) and log4j*.jar (from \lib\log4j).
4. Datamodel
We will later use the following datamodel for the example.
Create a Java project "de.vogella.spring.di.model" and create the following packages and classes.
package writer;
public interface IWriter {
public void writer(String s);
}
package writer;
public class Writer implements IWriter {
public void writer (String s){
System.out.println(s);
}
}
package writer;
public class NiceWriter implements IWriter {
public void writer (String s){
System.out.println("The string is " + s);
}
}
package testbean;
import writer.IWriter;
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.java" contains a setter for the actual writer. We will use the Spring Framework to inject the correct writer into this class.
5. Using dependency injection with annotations
As of Spring 2.5 it is possible to configure the dependency injection via annotations. I recommend to use this way of configuring your Spring beans. The next chapter will also describe the way to configure this via XML. Create a new Java project "de.vogella.spring.di.annotations.first" and include the minimal required spring jars into your classpath. Copy your model class from the de.vogella.spring.di.model project into this project. You need now to add annotations to your model to tell Spring which beans should be managed by Spring and how they should be connected. Add the @Service annotation the MySpringBeanWithDependency.java and NiceWriter.java. 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);
}
}
Under the src folder create a folder META-INF and create the following file in this folder. This is the Spring configuration file.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scan base-package="testbean" />
<context:component-scan base-package="writer" />
</beans>
You can also configure the log4j logger (this is optional) by copying the following file into the source folder.
|
Afer this setup you can wire the application together. Create a main class which reads the configuration file and starts the application.
package main;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import testbean.MySpringBeanWithDependency;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"META-INF/beans.xml");
BeanFactory factory = context;
MySpringBeanWithDependency test = (MySpringBeanWithDependency) factory
.getBean("mySpringBeanWithDependency");
test.run();
}
}
If you run the application then the class for the IWriterInterface will be inserted into the Test class. By applying the dependency injecting I can later replace this writer with a more sophisticated writer. As a result the class Test does not depend on the concrete Writer class, is extensible and can be easily tested.
6. Using dependency injection with XML
The following example will demonstrate the usage of the dependency injection via xml. The example will inject a writer into another class.
I think annotations rock in general, therefore I recommend not to use the XML configuration but the annotation one. If you have good reason to use the XML configuration please feel free to do so. |
Create a new Java project "de.vogella.spring.di.xml.first" and include the minimal required spring jars into your classpath. Copy your model class from the de.vogella.spring.di.model project into this project. Under the src folder create a folder META-INF and create the following file in this folder. This is the Spring configuration file.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="writer" class="writer.NiceWriter" />
<bean id="mySpringBeanWithDependency" class="testbean.MySpringBeanWithDependency">
<property name="writer" ref="writer" />
</bean>
</beans>
Again, you can now wire the application together. Create a main class which reads the configuration file and starts the application.
package main;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import testbean.MySpringBeanWithDependency;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"META-INF/beans.xml");
BeanFactory factory = context;
MySpringBeanWithDependency test = (MySpringBeanWithDependency) factory
.getBean("mySpringBeanWithDependency");
test.run();
}
}
3.1. @Autowired on Properties
The annotation can be used directly on properties, therefore eliminating the need for getters and setters:
1
2
3
4
5
6
7
@Component
(
"fooFormatter"
)
public
class
FooFormatter {
public
String format() {
return
"foo"
;
}
}
1
2
3
4
5
6
7
@Component
public
class
FooService {
@Autowired
private
FooFormatter fooFormatter;
}
In the above example, Spring looks for and injects fooFormatter when FooService is created.
3.2. @Autowired on Setters
The @Autowired annotation can be used on setter methods. In the below example, when the annotation is used on the setter method, the setter method is called with the instance of FooFormatter when FooService is created:
1
2
3
4
5
6
7
8
9
public
class
FooService {
private
FooFormatter fooFormatter;
@Autowired
public
void
setFooFormatter(FooFormatter fooFormatter) {
this
.fooFormatter = fooFormatter;
}
}
3.3. @Autowired on Constructors
The @Autowired annotation can also be used on constructors. In the below example, when the annotation is used on a constructor, an instance of FooFormatter is injected as an argument to the constructor when FooService is created:
1
2
3
4
5
6
7
8
9
public
class
FooService {
private
FooFormatter fooFormatter;
@Autowired
public
FooService(FooFormatter fooFormatter) {
this
.fooFormatter = fooFormatter;
}
}
215 comments:
«Oldest ‹Older 201 – 215 of 215This comprehensive breakdown of Dependency Injection (DI) in Java, especially within the Spring Framework, is incredibly insightful. The emphasis on decoupling components to enhance testability and maintainability resonates deeply. The practical examples, particularly the constructor-based DI, effectively illustrate how DI fosters cleaner and more modular code.
https://iimskills.com/financial-modelling-course-in-delhi/
This is one of a standout explanations of Dependency Injection I've read. The way you walk through the core concept of Inversion of Control, demonstrate it with the IWriter example, and then show the practical implementation in Spring with both annotations and XML is incredibly thorough.
It's fascinating how this core engineering principle of decoupling components for flexibility and testability applies in completely different professional domains. For example, in corporate finance, the exact same philosophy is used in financial modeling. Best practice dictates that all key assumptions (like revenue growth or interest rates) must be kept separate and "injected" into the calculation model. This allows analysts to test different scenarios and stress-test the business case without ever touching the core logic—very similar to how DI allows developers to use mock objects for testing.
It's a fundamental skill for building robust, flexible models, and it's a core concept taught in professional financial modeling courses in delhi
Thanks for such a detailed and well-explained article!
Really appreciate the effort you put into this post! The insights are clear, helpful, and genuinely made me think. It’s always refreshing to come across content that’s both informative and engaging. Looking forward to exploring more from you!
financial modeling courses in delhi
Very helpful explanation—cleared up several doubts I had on this topic.
I liked how simply the concepts were broken down for beginners.
Looking forward to more posts like this, especially with real-world examples.
Thanks for sharing such valuable content!
financial modeling courses in delhi
Great work explaining dependency injection in such a clear and concise way! Many tutorials focus only on the technical implementation, but you’ve taken the time to explain the reasoning and design benefits behind it. This post is definitely one I’ll be sharing with fellow developers who want to improve their Java code architecture.
financial modeling courses in delhi
financial modeling courses in delhi
Clear and well-explained! Dependency Injection can be a tricky concept for beginners, but this post does a great job of breaking it down. I really appreciate how you highlighted its role in promoting loose coupling and improving testability—two major wins for maintainable code.
The examples made it easy to visualize how DI works in practice, especially in frameworks like Spring or .NET. It’s one of those design patterns that, once understood, really elevates the quality of software architecture.
Thanks for demystifying it! Looking forward to more posts on design principles and best practices.
Clear explanation. Dependency Injection makes code easier to manage, test, and reuse. It breaks the tight link between classes, allowing you to switch parts without rewriting everything. This pattern fits well with frameworks like Spring, .NET, and Angular. If you want clean structure and easy testing, this approach helps you get there fast.
financial modeling courses in delhi
Your blog post is really great to see with detailed description. Thanks a lot for taking time to provide us this useful informative blog.
href="https://iimskills.com/financial-modelling-course-in-delhi/">financial modeling courses in delhi
Your explanation of dependency injection in Java is very well-written and beginner-friendly. I found the examples on how DI promotes decoupling and improves code maintainability especially useful. This is a critical concept for any Java developer working on scalable enterprise applications, and your practical tips make it easy to implement in real-world scenarios. Keep these Java tutorials coming—they’re great!
financial modeling courses in delhi
This article provides a clear and concise explanation of Dependency Injection (DI) in Java, highlighting its importance in creating modular and maintainable code.
The examples effectively demonstrate how DI promotes loose coupling and enhances testability in applications.
financial modeling courses in delhi
A clear and concise explanation of dependency injection! This piece effectively connects the concept to Inversion of Control and demonstrates why avoiding hard dependencies improves reusability and testing. Thank you for publishing such a straightforward take on a topic that’s often overcomplicated.
financial modeling courses in delhi
This is a very clear and detailed explanation of dependency injection and how it works in Java and Spring. I especially like the examples showing constructor, field, and setter injection – it really helps in understanding how DI promotes modularity and testability. The Spring example with MySpringBeanWithDependency makes the concept very practical. Thanks for breaking it down so thoroughly!
financial modeling courses in delhi
Spring performs dependency injection using three methods: setter injection, field injection, or constructor injection. Any class managed by Spring DI must follow the Java Bean standard.
financial modeling courses in delhi
"Great explanation of dependency injection! It’s one of those core design principles that really improves code maintainability, testability, and flexibility. By decoupling components and managing their dependencies externally, DI promotes cleaner architecture and makes unit testing much easier. This post does a solid job of breaking it down in simple terms—especially helpful for developers new to design patterns.
financial modeling courses in delhi
This blog is a great resource for anyone working with Oracle eBusiness ERP. The tips and expert solutions are really practical and make it easier to solve real-world challenges. Very helpful for both learners and professionals!
financial modeling courses in delhi
Post a Comment