In the post dependency injection in Spring we have already gone through the concept of dependency injection, in this post we’ll see in details one of the type of dependency injection- Setter dependency injection in Spring.
For another type of dependency injection, Constructor dependency injection check this post- Constructor Dependency Injection in Spring
Spring Setter dependency injection
In setter based DI Spring container calls setter methods on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean.
For configuring setter based dependencies you can use XML configuration as well as annotations. We’ll see examples of doing it using both of these ways.
Spring Setter dependency injection Example
In the example there is a class to place orders called Order and purchase can be done from an online store or a retail store. In Order class dependencies for the properties are injected using setter dependency injection.
public interface IStore { public void doPurchase(int items); }
public class OnlineStore implements IStore { public void doPurchase(int items) { System.out.println("Doing online purchase of " + items + " Items"); } }
public class RetailStore implements IStore { public void doPurchase(int items) { System.out.println("Doing purchase of " + items + " Items from a brick and mortar store"); } }
public class Order { private IStore store; private int items; public void setStore(IStore store) { this.store = store; } public void setItems(int items) { this.items = items; } public void buyItems() { store.doPurchase(items); } }
In the Order class these are two properties one reference to Istore type and another an int. There are setter methods for those properties which will be called by the Spring container to set the configured values.
If you are using XML configuration then beans are defined as given in the following XML-
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Store bean --> <bean id="store" class="com.knpcode.SpringProject.RetailStore" /> <!-- Order bean with dependencies --> <bean id="orderBean" class="com.knpcode.SpringProject.Order"> <property name="store" ref="store" /> <property name="items" value="20" /> </bean> </beans>
For providing setter dependencies <property> tag is used.
- When dependency is for another bean “ref” attribute is used.
- For any primitive type or String “value” attribute is used.
You can use the following class with main method to read the configuration and call the bean method.
public class App { public static void main( String[] args ){ // create context using configuration ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml"); Order order = (Order) context.getBean("orderBean"); order.buyItems(); // close the context context.close(); } }
Spring Setter dependency injection using annotations
If you want to configure setter dependencies in Spring using annotations then you will have to use @Service or @Component annotation with the classes to signify that these are Spring managed component and will be automatically discovered when component scanning is done.
Annotate setter methods with @autowired to inject the setter dependencies automatically.
@Service public class OnlineStore implements IStore { public void doPurchase(int items) { System.out.println("Doing online purchase of " + items + " Items"); } }
@Service public class RetailStore implements IStore { public void doPurchase(int items) { System.out.println("Doing purchase of " + items + " Items from a brick and mortar store"); } }
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class Order { private IStore store; @Value("20") private int items; @Autowired @Qualifier("onlineStore") public void setStore(IStore store) { this.store = store; } public void buyItems() { store.doPurchase(items); } }
Since there are two objects of type store so @Qualifier annotation has been used to tell which bean has to be wired otherwise you will get an error "No qualifying bean of type 'com.knpcode.SpringProject.IStore' available"
Autowiring works with references only so primitive value is provided using @Value annotation.
If you want to use XML to set up component scanning for automatically discovering beans then it can be done using following XML.
<?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="com.knpcode.SpringProject" /> </beans>
XML configuration won’t have any dependencies now only <context:component-scan> tag.
Constructor-based or setter-based Dependency injection
As per Spring documentation constructor based DI is preferred over 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.
The Spring team generally advocates constructor injection as it enables one to implement application components as
immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are
always returned to client (calling) code in a fully initialized state.
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 everywhere the code uses the dependency."
That's all for the topic Setter Dependency Injection in Spring. If something is missing or you have something to share about the topic please write a comment.
You may also like
- Spring Java-based Configuration Example
- Spring Autowiring Example Using XML Configuration
- Spring Bean Scopes
- spring-boot-starter-parent in Spring Boot
- Spring Boot Hello World Application
- Java Collections Framework Tutorial
- Polymorphism in Java – OOPS Concepts
- Java PDFBox Example - Read Text And Extract Image From PDF
- Method Overloading in Python With Examples
- Redux in React With Examples
No comments:
Post a Comment