Site icon SpringHow

Setter Dependency Injection in Spring Framework

Introduction

Setter based dependency injection is one of the ways spring allows to do DI. As setters let us update object properties after its creation, This behaviour is a perfect candidate to add optional dependencies in a Spring IoC container. Also, Setter injection plays as an alternative when Constructor Dependency Injection is not possible.

For instance, Satisfying all dependencies at the constructor will slow down the application. But if we could initialize the required dependencies, setters will help to inject optional dependencies. Let’s see both XML and annotation-based configurations.

But before that, You need to add Spring Context as a dependency to maven configuration.

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.5</version>
</dependency>Code language: HTML, XML (xml)

XML Spring config for Setter injection

The setter injection uses the property elements for setter injection. For each dependency, you need to define a property element inside your bean definition. The name attribute of this tag takes the field name.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.springhow.beans.UserService"/>

    <bean class="com.springhow.beans.OrderService">
        <!-- use an already existing bean as reference -->
        <property name="userService" ref="userService"/>
        <!-- or create a bean as and when required -->
        <property name="paymentService">
            <bean class="com.springhow.beans.PaymentService"/>
        </property>
    </bean>

</beans>
Code language: HTML, XML (xml)

As you see, You can use an already existing bean as a setter injected bean. If you need to, you can create one on demand. You can see both of these highlighted in the snippet above.

Spring Annotation Config for Setter dependency injection

In the annotation config, we do not need any XML files to load the beans and context. Instead, You can define the bean definitions directly as java annotations. For example, you can define the OrderService as shown below.

@Component
public class OrderService {

    private PaymentService paymentService;
    private UserService userService;

    public void performOrder() {
        userService.setupUser();
        paymentService.performPayment();
    }

    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    @Autowired
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}
Code language: Java (java)

And for the autowiring to work, we need to define the beans required somewhere else. In this case, a BeanConfig.java file.

@Configuration
@ComponentScan("com.springhow.beans")
public class BeanConfig {

    @Bean
    PaymentService getPaymentService() {
        return new PaymentService();
    }

    @Bean
    UserService getUserService() {
        return new UserService();
    }

}Code language: PHP (php)

Also, you can mix static initialization and setter injection. For instance, the following example replicates the XML config we have done earlier.

//same as the XML config we have done earlier.
@Bean
OrderService getOrderService(UserService userService) {
    OrderService orderService = new OrderService();
    orderService.setUserService(userService);
    orderService.setPaymentService(new PaymentService());
    return orderService;
}Code language: Java (java)

In this bean definition, the userService will be autowired. And we supplied a PaymentService by ourselves as we did in the XML config.

When to use Setter Injection?

Spring advises using constructor injection whenever possible. That doesn’t mean setter injection has no place. Some classes from third party libraries may not have proper constructors. Also, Injecting all dependencies using a constructor makes sense if the dependencies are very few. While constructor injection may suffer from cyclic dependencies, setter injection can easily avoid such situation without modifying the classes.

Also, When spring was preferring setter injection at the earlier times when the framework was still evolving. So other libraries that used Spring also defined their classes the same way. This is why you still need to use setter injection in some cases.

You can even mix up constructor and setter injection together by defining a component with constructor and also defining a setter with @Autowired annotation.


If you liked this article, you may also like the following write ups.

Exit mobile version