Show List
Spring Introduction
Spring is open source application development framework for Java. Spring makes programming Java quicker and easier. Spring framework provides lots of tools out of the box so reduces the code required. There are also extensions and third party libraries to add features. Spring framework uses dependency injection (DI) to provide features and functionalities.
Spring framework was first released in June 2003.
Dependency Injection
Dependency injection is providing an object its dependencies instead of having it construct them itself. Dependencies can be injected in many ways such as through a constructor or a setter. Spring framework not necessarily required for dependency injection. You can initialize the dependency object and pass through constructor or setter. Spring makes dependency injection simpler. Dependency injection helps in:
- Decoupling the creation of object
- ability to replace dependencies without changing the class that uses it
- Promotes "Code to interface not to implementation" principle
- Ability to create and use mock dependency during test
The Spring container is at the core of the Spring Framework. It will create the objects, wire them together, configure them, and manage their complete life cycle from creation till destruction. It reads the dependencies from XML, annotations or JavaConfig and at the time of initializing its context it creates all the beans. The dependencies are wired using reflection API. There are two types of containers. Application Context container provides additional features:
Bean Factory
- Bean instantiation/wiring
Application Context
- Bean instantiation/wiring
- Automatic BeanPostProcessor registration
- Automatic BeanFactoryPostProcessor registration
- Convenient MessageSource access (for i18n)
- ApplicationEvent publication
Some differences between Bean Factory and application Context:
- BeanFactory uses lazy initialization but ApplicationContext uses eager initialization. In BeanFactory, bean is created when getBeans() method is called, but bean is created upfront in case of ApplicationContext when the ApplicationContext object is created.
- BeanFactory does not support internationalization but ApplicationContext supports internationalization.
- With BeanFactory annotation based dependency injection is not supported but annotation based dependency injection is supported in ApplicationContext.
Spring Modules
Spring features are organized in about 20 modules. These modules are grouped together based on their primary feature into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented Programming), Instrumentation and Test.
Core Container
- Core and Beans modules provide Dependency Injection features
- Context module provides way to access objects
- Expression Language module provides expression language for querying and manipulating an object graph at runtime
Data Access/Integration
- JDBC module provides abstraction layer that removes the need to do tedious JDBC coding and parsing of database-vendor specific error codes.
- ORM module provides integration layers for popular object-relational mapping APIs, including JPA, JDO, Hibernate, and iBatis.
- OXM module provides an abstraction layer for using a number of Object/XML mapping implementations. Supported technologies include JAXB, Castor, XMLBeans, JiBX and XStream.
- JMS module provides support for the Java Messaging Service. It contains features for both producing and consuming messages.
- Transaction module provides a way to do programmatic as well as declarative transaction management, not only for classes implementing special interfaces, but for all your POJOs (plain old Java objects).
Web
- Web module provides basic web-oriented integration features, such as multipart file-upload functionality, the initialization of the IoC container using servlet listeners and a web-oriented application context.
- Web-Servlet module provides Model-View-Controller (MVC) implementation for web-applications.
- Web-Portlet module provides the MVC implementation to be used in a portlet environment and mirrors what is provided in the Web-Servlet module.
AOP
AOP module provides an aspect-oriented programming implementation allowing to define, for example, method-interceptors and pointcuts to cleanly decouple code implementing functionality.
Instrumentation
Instrumentation module provides class instrumentation support and classloader implementations to be used in certain application servers
Test
Test module contains the Test Framework that supports testing Spring components using JUnit or TestNG
Dependency Injection using XML Configuration
Step1: Create Maven project in IDE. File > New > Maven Project
Step2: Add spring-context dependency in the the pom file. This is used for dependency injection.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
Step3: Create consumer class (ConsumerA.java) and dependent class (DependencyA.java)
Step4: Configure dependency among classes using xml file (xmlFileA.xml) in the src/main/resources folder. Sample:
<?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
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="dependencyA" class="com.demo.DependencyA" />
<bean id="dependencyB" class="com.demo.DependencyB" />
<bean id="consumerA" class="com.demo.ConsumerA">
<constructor-arg ref="dependencyA" />
</bean>
<bean id="consumerB" class="com.demo.ConsumerB">
<property name="paramA" ref="dependencyB" />
</bean>
</beans>
Here dependency injection in bean consumerA is done using constructor injection and bean consumerB is done using setter injection.
Step5: Using the bean. Load the application context from the created xml file. Get the bean and cast to corresponding class type.
package com.demo.service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDependencyExample {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("xmlFileA.xml");
ConsumerA consumer = (ConsumerA) context.getBean("consumerA");
consumer.process();
}
}
Dependency Injection using XML Configuration File and Annotations
Steps are same as above. Instead of providing the dependencies in the xmlFileA.xml file, @Component, @Service, @Resource, @Autowire and other annotations are used in the classes to define and provide dependencies.
Step1: Create Maven project in IDE. File > New > Maven Project
Step2: Add spring-context dependency in the the pom file.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
Step3: Create consumer class (ConsumerA.java) and dependent class (DependencyA.java) and add annotations (e.g. @Component, @Service, @Resource, @Autowire)
Step4: Create xml file (xmlFileA.xml) in the src/main/resources folder and specify annotation wiring:
<?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.dependencies, com.consumers" />
</beans>
Step5: Using the bean. Load the application context from the created xml file.
package com.demo.service;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SpringDependencyExample {
public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("xmlFileA.xml");
ConsumerA consumer = (ConsumerA) context.getBean("consumerA");
consumer.process();
}
}
Dependency Injection Using Java Based Configuration
Here a Java class is used to define the beans instead of an xml file (xmlFileA.xml in the example above). @Configuration annotation is used to declare a class as configuration class that provides beans definitions. Method with @Bean annotation returns a bean that is registered in the Spring application context.
Step1: Create Maven project in IDE. File > New > Maven Project
Step2: Add spring-context dependency in the the pom file.
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
Step3: Create consumer class (ConsumerA.java) and dependent class (DependencyA.java). Annotations are not required in the classes as beans are going to be created in the configuration class in step 4.
Step4: Create Java configuration class with @Configuration annotation
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ConfigClass {
@Bean
public ConsumerA getConsumerA(){
DependencyA dependencyA = new DependencyA();
return new ConsumerA(dependencyA);
}
}
Step5: Use ConfigClass to load application context and get beans
package com.example.demo.service;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class SpringDependencyExample {
public static void main(String[] args) {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext(ConfigClass.class);
ConsumerA consumer = (ConsumerA) context.getBean("consumerA");
consumer.process();
}
}
Additional Note: We can exclude @Bean method from the ConfigClass if we use annotations (e.g. @Component, @Service etc) in the classes in step 3. @ComponentScan on the ConfigClass will take care of scanning those beans.
package com.example.demo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ComponentScan(basePackages = "com.dependencies, com.consumers")
public class ConfigClass {
}
Leave a Comment