0% found this document useful (0 votes)
3 views10 pages

Dependency Injection - Spring Framework

Uploaded by

nupsurer
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views10 pages

Dependency Injection - Spring Framework

Uploaded by

nupsurer
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Spring Framework / Core Technologies / The IoC Container / Dependencies / Dependency Injection

Dependency Injection
Dependency Injection

Constructor-based Dependency Injection


Constructor Argument Resolution
Setter-based Dependency Injection
Dependency Resolution Process
Examples of Dependency Injection

Dependency injection (DI) is a process whereby objects define their dependencies (that is, the other
objects with which they work) only through constructor arguments, arguments to a factory method,
or properties that are set on the object instance after it is constructed or returned from a factory
method. The container then injects those dependencies when it creates the bean. This process is fun‐
damentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the in‐
stantiation or location of its dependencies on its own by using direct construction of classes or the
Service Locator pattern.

Code is cleaner with the DI principle, and decoupling is more effective when objects are provided
with their dependencies. The object does not look up its dependencies and does not know the loca‐
tion or class of the dependencies. As a result, your classes become easier to test, particularly when
the dependencies are on interfaces or abstract base classes, which allow for stub or mock implemen‐
tations to be used in unit tests.

DI exists in two major variants: Constructor-based dependency injection and Setter-based depen‐
dency injection.

Constructor-based Dependency Injection


Constructor-based DI is accomplished by the container invoking a constructor with a number of ar‐
guments, each representing a dependency. Calling a static factory method with specific argu‐
ments to construct the bean is nearly equivalent, and this discussion treats arguments to a construc‐
tor and to a static factory method similarly. The following example shows a class that can only be
dependency-injected with constructor injection:

Java Kotlin

JAVA
public class SimpleMovieLister {
// the SimpleMovieLister has a dependency on a MovieFinder
private final MovieFinder movieFinder;

// a constructor so that the Spring container can inject a MovieFinder


public SimpleMovieLister(MovieFinder movieFinder) {
[Link] = movieFinder;
}

// business logic that actually uses the injected MovieFinder is omitted...


}

Notice that there is nothing special about this class. It is a POJO that has no dependencies on con‐
tainer specific interfaces, base classes, or annotations.

Constructor Argument Resolution

Constructor argument resolution matching occurs by using the argument’s type. If no potential am‐
biguity exists in the constructor arguments of a bean definition, the order in which the constructor
arguments are defined in a bean definition is the order in which those arguments are supplied to the
appropriate constructor when the bean is being instantiated. Consider the following class:

Java Kotlin

JAVA
package x.y;

public class ThingOne {

public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {


// ...
}
}

Assuming that the ThingTwo and ThingThree classes are not related by inheritance, no potential
ambiguity exists. Thus, the following configuration works fine, and you do not need to specify the
constructor argument indexes or types explicitly in the <constructor-arg/> element.

XML
<beans>
<bean id="beanOne" class="[Link]">
<constructor-arg ref="beanTwo"/>
<constructor-arg ref="beanThree"/>
</bean>

<bean id="beanTwo" class="[Link]"/>

<bean id="beanThree" class="[Link]"/>


</beans>
When another bean is referenced, the type is known, and matching can occur (as was the case with
the preceding example). When a simple type is used, such as <value>true</value> , Spring cannot
determine the type of the value, and so cannot match by type without help. Consider the following
class:

Java Kotlin

JAVA
package examples;

public class ExampleBean {

// Number of years to calculate the Ultimate Answer


private final int years;

// The Answer to Life, the Universe, and Everything


private final String ultimateAnswer;

public ExampleBean(int years, String ultimateAnswer) {


[Link] = years;
[Link] = ultimateAnswer;
}
}

Constructor argument type matching

In the preceding scenario, the container can use type matching with simple types if you explicitly
specify the type of the constructor argument via the type attribute, as the following example shows:

XML
<bean id="exampleBean" class="[Link]">
<constructor-arg type="int" value="7500000"/>
<constructor-arg type="[Link]" value="42"/>
</bean>

Constructor argument index

You can use the index attribute to specify explicitly the index of constructor arguments, as the fol‐
lowing example shows:

XML
<bean id="exampleBean" class="[Link]">
<constructor-arg index="0" value="7500000"/>
<constructor-arg index="1" value="42"/>
</bean>

In addition to resolving the ambiguity of multiple simple values, specifying an index resolves ambi‐
guity where a constructor has two arguments of the same type.
The index is 0-based.

Constructor argument name

You can also use the constructor parameter name for value disambiguation, as the following example
shows:

XML
<bean id="exampleBean" class="[Link]">
<constructor-arg name="years" value="7500000"/>
<constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Keep in mind that, to make this work out of the box, your code must be compiled with the -
parameters flag enabled so that Spring can look up the parameter name from the constructor. If
you cannot or do not want to compile your code with the -parameters flag, you can use the
@ConstructorProperties JDK annotation to explicitly name your constructor arguments. The sample
class would then have to look as follows:

Java Kotlin

JAVA
package examples;

public class ExampleBean {

// Fields omitted

@ConstructorProperties({"years", "ultimateAnswer"})
public ExampleBean(int years, String ultimateAnswer) {
[Link] = years;
[Link] = ultimateAnswer;
}
}

Setter-based Dependency Injection


Setter-based DI is accomplished by the container calling setter methods on your beans after invok‐
ing a no-argument constructor or a no-argument static factory method to instantiate your bean.

The following example shows a class that can only be dependency-injected by using pure setter in‐
jection. This class is conventional Java. It is a POJO that has no dependencies on container specific in‐
terfaces, base classes, or annotations.

Java Kotlin
JAVA
public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on the MovieFinder


private MovieFinder movieFinder;

// a setter method so that the Spring container can inject a MovieFinder


public void setMovieFinder(MovieFinder movieFinder) {
[Link] = movieFinder;
}

// business logic that actually uses the injected MovieFinder is omitted...


}

The ApplicationContext supports constructor-based and setter-based DI for the beans it man‐
ages. It also supports setter-based DI after some dependencies have already been injected through
the constructor approach. You configure the dependencies in the form of a BeanDefinition , which
you use in conjunction with PropertyEditor instances to convert properties from one format to
another. However, most Spring users do not work with these classes directly (that is, programmati‐
cally) but rather with XML bean definitions, annotated components (that is, classes annotated with
@Component , @Controller , and so forth), or @Bean methods in Java-based @Configuration
classes. These sources are then converted internally into instances of BeanDefinition and used to
load an entire Spring IoC container instance.

Constructor-based or setter-based DI?


Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use
constructors for mandatory dependencies and setter methods or configuration methods for
optional dependencies. Note that use of the @Autowired annotation on a setter method can
be used to make the property be a required dependency; however, constructor injection with
programmatic validation of arguments is preferable.

The Spring team generally advocates constructor injection, as it lets you implement applica‐
tion components as immutable objects and ensures that required dependencies are not
null . Furthermore, constructor-injected components are always returned to the client (call‐
ing) code in a fully initialized state. As a side note, a large number of constructor arguments is
a bad code smell, implying that the class likely has too many responsibilities and should be
refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned
reasonable default values within the class. Otherwise, not-null checks must be performed ev‐
erywhere the code uses the dependency. One benefit of setter injection is that setter methods
make objects of that class amenable to reconfiguration or re-injection later. Management
through JMX MBeans is therefore a compelling use case for setter injection.
Use the DI style that makes the most sense for a particular class. Sometimes, when dealing
with third-party classes for which you do not have the source, the choice is made for you. For
example, if a third-party class does not expose any setter methods, then constructor injection
may be the only available form of DI.

Dependency Resolution Process


The container performs bean dependency resolution as follows:

The ApplicationContext is created and initialized with configuration metadata that describes
all the beans. Configuration metadata can be specified by XML, Java code, or annotations.

For each bean, its dependencies are expressed in the form of properties, constructor arguments,
or arguments to the static-factory method (if you use that instead of a normal constructor).
These dependencies are provided to the bean, when the bean is actually created.

Each property or constructor argument is an actual definition of the value to set, or a reference
to another bean in the container.

Each property or constructor argument that is a value is converted from its specified format to
the actual type of that property or constructor argument. By default, Spring can convert a value
supplied in string format to all built-in types, such as int , long , String , boolean , and so
forth.

The Spring container validates the configuration of each bean as the container is created. However,
the bean properties themselves are not set until the bean is actually created. Beans that are single‐
ton-scoped and set to be pre-instantiated (the default) are created when the container is created.
Scopes are defined in Bean Scopes. Otherwise, the bean is created only when it is requested.
Creation of a bean potentially causes a graph of beans to be created, as the bean’s dependencies
and its dependencies' dependencies (and so on) are created and assigned. Note that resolution mis‐
matches among those dependencies may show up late — that is, on first creation of the affected
bean.

Circular dependencies
If you use predominantly constructor injection, it is possible to create an unresolvable circular
dependency scenario.

For example: Class A requires an instance of class B through constructor injection, and class B
requires an instance of class A through constructor injection. If you configure beans for
classes A and B to be injected into each other, the Spring IoC container detects this circular
reference at runtime, and throws a BeanCurrentlyInCreationException .
One possible solution is to edit the source code of some classes to be configured by setters
rather than constructors. Alternatively, avoid constructor injection and use setter injection
only. In other words, although it is not recommended, you can configure circular dependen‐
cies with setter injection.

Unlike the typical case (with no circular dependencies), a circular dependency between bean A
and bean B forces one of the beans to be injected into the other prior to being fully initialized
itself (a classic chicken-and-egg scenario).

You can generally trust Spring to do the right thing. It detects configuration problems, such as refer‐
ences to non-existent beans and circular dependencies, at container load-time. Spring sets proper‐
ties and resolves dependencies as late as possible, when the bean is actually created. This means that
a Spring container that has loaded correctly can later generate an exception when you request an
object if there is a problem creating that object or one of its dependencies — for example, the bean
throws an exception as a result of a missing or invalid property. This potentially delayed visibility of
some configuration issues is why ApplicationContext implementations by default pre-instantiate
singleton beans. At the cost of some upfront time and memory to create these beans before they are
actually needed, you discover configuration issues when the ApplicationContext is created, not
later. You can still override this default behavior so that singleton beans initialize lazily, rather than
being eagerly pre-instantiated.

If no circular dependencies exist, when one or more collaborating beans are being injected into a de‐
pendent bean, each collaborating bean is totally configured prior to being injected into the depen‐
dent bean. This means that, if bean A has a dependency on bean B, the Spring IoC container com‐
pletely configures bean B prior to invoking the setter method on bean A. In other words, the bean is
instantiated (if it is not a pre-instantiated singleton), its dependencies are set, and the relevant lifecy‐
cle methods (such as a configured init method or the InitializingBean callback method) are invoked.

Examples of Dependency Injection


The following example uses XML-based configuration metadata for setter-based DI. A small part of a
Spring XML configuration file specifies some bean definitions as follows:

XML
<bean id="exampleBean" class="[Link]">
<!-- setter injection using the nested ref element -->
<property name="beanOne">
<ref bean="anotherExampleBean"/>
</property>

<!-- setter injection using the neater ref attribute -->


<property name="beanTwo" ref="yetAnotherBean"/>
<property name="integerProperty" value="1"/>
</bean>
<bean id="anotherExampleBean" class="[Link]"/>
<bean id="yetAnotherBean" class="[Link]"/>

The following example shows the corresponding ExampleBean class:

Java Kotlin

JAVA
public class ExampleBean {

private AnotherBean beanOne;

private YetAnotherBean beanTwo;

private int i;

public void setBeanOne(AnotherBean beanOne) {


[Link] = beanOne;
}

public void setBeanTwo(YetAnotherBean beanTwo) {


[Link] = beanTwo;
}

public void setIntegerProperty(int i) {


this.i = i;
}
}

In the preceding example, setters are declared to match against the properties specified in the XML
file. The following example uses constructor-based DI:

XML
<bean id="exampleBean" class="[Link]">
<!-- constructor injection using the nested ref element -->
<constructor-arg>
<ref bean="anotherExampleBean"/>
</constructor-arg>

<!-- constructor injection using the neater ref attribute -->


<constructor-arg ref="yetAnotherBean"/>

<constructor-arg type="int" value="1"/>


</bean>

<bean id="anotherExampleBean" class="[Link]"/>


<bean id="yetAnotherBean" class="[Link]"/>

The following example shows the corresponding ExampleBean class:


Java Kotlin

JAVA
public class ExampleBean {

private AnotherBean beanOne;

private YetAnotherBean beanTwo;

private int i;

public ExampleBean(
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
[Link] = anotherBean;
[Link] = yetAnotherBean;
this.i = i;
}
}

The constructor arguments specified in the bean definition are used as arguments to the constructor
of the ExampleBean .

Now consider a variant of this example, where, instead of using a constructor, Spring is told to call a
static factory method to return an instance of the object:

XML
<bean id="exampleBean" class="[Link]" factory-method="createInstance">
<constructor-arg ref="anotherExampleBean"/>
<constructor-arg ref="yetAnotherBean"/>
<constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="[Link]"/>


<bean id="yetAnotherBean" class="[Link]"/>

The following example shows the corresponding ExampleBean class:

Java Kotlin

JAVA
public class ExampleBean {

// a private constructor
private ExampleBean(...) {
...
}

// a static factory method; the arguments to this method can be


// considered the dependencies of the bean that is returned,
// regardless of how those arguments are actually used.
public static ExampleBean createInstance (
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
ExampleBean eb = new ExampleBean (...);
// some other operations...
return eb;
}
}

Arguments to the static factory method are supplied by <constructor-arg/> elements, exactly
the same as if a constructor had actually been used. The type of the class being returned by the fac‐
tory method does not have to be of the same type as the class that contains the static factory
method (although, in this example, it is). An instance (non-static) factory method can be used in an
essentially identical fashion (aside from the use of the factory-bean attribute instead of the class
attribute), so we do not discuss those details here.

Copyright © 2005 - 2026 Broadcom. All Rights Reserved. The term "Broadcom" refers to
Broadcom Inc. and/or its subsidiaries.
Terms of Use • Privacy • Trademark Guidelines • Thank you • Your California Privacy Rights
• Cookies Settings

Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™
are trademarks or registered trademarks of the Apache Software Foundation in the
United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are
trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the
Linux Foundation in the United States and other countries. Linux® is the registered
trademark of Linus Torvalds in the United States and other countries. Windows® and
Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and
“Amazon Web Services” are trademarks or registered trademarks of [Link] Inc. or
its affiliates. All other trademarks and copyrights are property of their respective owners
and are only mentioned for informative purposes. Other names may be trademarks of
their respective owners.

You might also like