A primary goal of Spring is to keep components as independent as possible, which allows these components to be reused , and also provides possibility to unit test them independently. Spring Dependency Injection principal fulfill this goal via injecting the dependency one component might need to complete its job, rather that component itself finding it’s dependency. In this post we will focus on XML based configuration.Check out Annotation example as well. Let’s get going.
Spring provides mainly two ways for dependency injection
In this approach, dependency is injected/provided using Setter Method. Property Setter approach is more widely used in industry and simple to understand.
a) Create Sample Bean
package com.websystique.spring; import com.websystique.spring.domain.Encryption; public class Communication { private Messaging messaging; /* * DI via Setter */ public void setMessaging(Messaging messaging){ this.messaging = messaging; } public void communicate(){ messaging.sendMessage(); } }
b) Create Helper POJO interface and implementation
package com.websystique.spring.domain; public interface Messaging { public void sendMessage(); }
package com.websystique.spring.domain.impl; import com.websystique.spring.domain.Messaging; public class ActiveMQMessaging implements Messaging{ public void sendMessage() { System.out.println("Sending Message via Active MQ"); } }
c) Create Spring Configuration 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" /> <bean id="communication" class="com.websystique.spring.Communication"> <property name="messaging"> <ref bean="activeMqMessaging" /> </property> </bean> </beans>
In above XML configuration, Spring will inject ‘activeMqMessaging’ bean into ‘communication’ bean using setter dependency injection. Communication’s setter method [setMessaging(Messaging messaing)] will be called to set the property.
d) create main and run application
package com.websystique.spring; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppMain { public static void main(String args[]){ AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml"); Communication app = (Communication)context.getBean("communication"); app.communicate(); } }
You will see following output :
Sending Message via Active MQ
In this approach, Spring injects the required dependency via Constructor argument[s].
a) Create Sample Bean
package com.websystique.spring; import com.websystique.spring.domain.Encryption; public class Communication { private Encryption encryption; /* * DI via Constructor Injection */ public Communication(Encryption encryption){ this.encryption = encryption; } public void communicate(){ encryption.encryptData(); } }
b) Create Helper POJO interface and implementation
package com.websystique.spring.domain; public interface Encryption { public void encryptData(); }
package com.websystique.spring.domain.impl; import com.websystique.spring.domain.Encryption; public class RSAEncryption implements Encryption{ public void encryptData() { System.out.println("Encrypting data using RSA Encryption"); } }
c) Create Spring Configuration 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" /> <bean id="communication" class="com.websystique.spring.Communication"> <constructor-arg> <ref bean="rsaEncryption" /> </constructor-arg> </bean> </beans>
In above XML configuration, Spring will inject ‘rsaEncryption’ bean into ‘communication’ bean using constructor dependency injection. Communication’s one arg Constructor[ Constructor(Encryption encryption)] will be called.
Remark: Although constructor injection seems simple, it can easily lead to infamous constructor ambiguities in case you have multiple constructors with same number of arguments but different types and if implicit conversion is possible between different types. It happens mostly with primitive type (int, String etc..). You can get rid of these ambiguities using ‘type’ attribute of constructor-arg element to specify exact type of argument e.g.
<bean id="communication" class="com.websystique.spring.Communication"> <constructor-arg type="com.websystique.spring.domain.Encryption"> <ref bean="rsaEncryption" /> </constructor-arg> </bean>
d) create main and run application
package com.websystique.spring; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppMain { public static void main(String args[]){ AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml"); Communication app = (Communication)context.getBean("communication"); app.communicate(); } }
You will see following output :
Encrypting data using RSA Encryption
Using both approach together on same Bean
It is also possible to use them together in same bean, although on different items.
Bean Class
package com.websystique.spring; import com.websystique.spring.domain.Encryption; import com.websystique.spring.domain.Messaging; public class Communication { private Messaging messaging; private Encryption encryption; /* * DI via Constructor Injection */ public Communication(Encryption encryption){ this.encryption = encryption; } /* * DI via Setter */ public void setMessaging(Messaging messaging){ this.messaging = messaging; } public void communicate(){ encryption.encryptData(); messaging.sendMessage(); } }
Spring Configuration Class
package com.websystique.spring.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Description; import com.websystique.spring.Communication; import com.websystique.spring.domain.Encryption; import com.websystique.spring.domain.Messaging; import com.websystique.spring.domain.impl.ActiveMQMessaging; import com.websystique.spring.domain.impl.RSAEncryption; @Configuration public class AppConfig { @Bean(name = "communication") public Communication communication() { Communication communication = new Communication(encryption()); communication.setMessaging(messaging()); return communication; } @Bean(name = "encryption") @Description("This bean will be injected via setter injection") public Encryption encryption() { return new RSAEncryption(); } @Bean(name = "messaging") @Description("This bean will be injected via setter injection") public Messaging messaging() { return new ActiveMQMessaging(); } }
Spring XML configuration
<?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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"> <bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" /> <bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" /> <bean id="communication" class="com.websystique.spring.Communication"> <constructor-arg> <ref bean="rsaEncryption" /> </constructor-arg> <property name="messaging"> <ref bean="activeMqMessaging" /> </property> </bean> </beans>
In above configuration, we are using Property Setter approach to inject ‘activeMqMessaging’ bean into ‘messaging’ property. On the other hand, we are using Constructor Injection approach to inject ‘rsaEncryption’ bean into Communication constructor.
Run Main
package com.websystique.spring; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class AppMain { public static void main(String args[]){ AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml"); Communication app = (Communication)context.getBean("communication"); app.communicate(); } }
You will see following output :
Encrypting data using RSA Encryption Sending Message via Active MQ
That’s it.
Below is the Directory Structure for this post:
And referenced pom.xml for this project is:
<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.websystique.spring</groupId> <artifactId>SpringDIWithXMLExample</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <name>SpringDIWithXMLExample</name> <properties> <springframework.version>4.0.6.RELEASE</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${springframework.version}</version> </dependency> </dependencies> </project>
References
If you like tutorials on this site, why not take a step further and connect me on Facebook , Google Plus & Twitter as well? I would love to hear your thoughts on these articles, it will help improve further our learning process.
In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…
Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…
Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…
Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…
Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…
This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…
View Comments
Nice Article ! But the Java Config should use
AnnotationConfigApplicationContext and instead of
ClassPathXmlApplicationContext. It would be helpful for others if you could correct this.
"It happens mostly with primitive type (int, String etc..)..."
String is not a primitive type ;) Still great job, hats off to you!