Ryan Thelin
Posted on May 5, 2021
While often overlooked as old-fashioned, the Spring Framework is still a popular application development tool desired by enterprise companies across the globe. Spring offers unparalleled control, top-notch security, and a time-saving dependency system using Spring Beans.
However, Spring is also notoriously difficult to learn due to its number of options and complex toolset.
Today, we'll help you start your Spring development journey with a beginner tutorial on how and why to use Spring. In the end, we'll even get you started on your first Spring portfolio project.
Here’s what we’ll cover today:
- What is the Spring Framework?
- Salient features of Spring
- Spring Architecture and Components
- Get started with Spring
- Advanced Spring concepts to learn next
Learn Spring in half the time
Learn professional-level Spring techniques quickly with hands-on lessons.
The Complete Guide to Spring 5 and Spring Boot 2
What is the Spring Framework?
Spring is a lightweight, open-source application development framework that uses Java Enterprise Edition (Java EE) and Enterprise JavaBeans model (EJB).
Spring is often thought of as a "framework of frameworks" because it supports other integrated frameworks in the Java ecosystem like Struts, Hibernate, and Tapestry. Spring comes in many variants that are tailored to particular uses such as Spring MVC, Spring Boot, or Spring Security.
Spring is known for its dependency injection and Inversion of Control (IoC) systems, which allow you to create large-scale, loosely-coupled applications with ease. Spring is especially suited for financial and enterprise applications due to its speed, security, and easy-to-build transaction systems. The top employers of Spring developers are Citibank, eBay, Visa, and J.P. Morgan.
Overall, Spring Framework allows you to create enterprise-scale applications that are secure and can automatically handle low-level functionalities like maintaining container lifecycles and managing dependencies.
Advantages of Spring
- Plain Old Java Object (POJO): Spring applications just use normal Java objects rather than servers or enterprise containers. This makes applications more lightweight.
- Modularity IoC and MVC allows you to reuse components across your application without manually managing the dependencies of each
- Strong support for Java ecosystem: Spring makes innovative uses of pre-existing technologies, such as ORM frameworks, JEE, and JDK timers
- Scalable transactions: Spring offers a consistent, scalable transaction management interface for both local transactions and global transactions. This includes caching protocols.
- Secure: Easy to implement security modules with authentication and validation features.
- Flexible Configs: Can opt to use Java-based annotations or XML configuration
Disadvantages of Spring
- Complexity: Spring Framework opts for increased control and complexity over ease of use. Spring is therefore harder to pick up than other web frameworks. While very powerful, Spring is best suited for experienced developers that can handle its steep learning curve.
- Parallel Mechanisms: Spring's wide range of options means a single task can be accomplished in several ways. You'll need intricate knowledge of your available tools to choose the ideal solution and avoid cross-team confusion.
- Lacking robust documentation: Spring's documentation is missing clear guidelines on a number of topics, especially around cybersecurity techniques. It's up to users to deal with common attacks like cross-site forgery and scripting attacks. > Many of these disadvantages were addressed by the invention of the Spring Boot module, which is highly opinionated and designed for microservice architectures. > > Most modern Spring applications are built on Boot but there are many older applications still maintained by long-standing companies.
Features of Spring
- Inversion of Control (IoC): Shifts responsibility for dependencies from objects to the framework itself. Without IoC, each object must handle its own instance of the dependency. With IoC, the object simply lists that it needs a certain dependency and the framework configures and manages it automatically. This simplifies the app development process by consolidating the dependency system and reducing the workload on individual classes.
- Aspect-Oriented Programming: Spring AOP allows you to have different class loaders to increase modularity and separate cross-cutting concerns.
- Dependency Injection: The process Spring uses to automatically manage the dependencies of beans. Spring checks which beans are required for a particular bean to function and injects them as a dependency. Spring can perform dependency injection by using a constructor or by using a setter method.
- Container Lifecycle Management: Automatically creates, manages, and configures application objects.
- MVC support: Supports the MVC web architecture that separates functionalities between model, view, and controller layers.
- Error Handling: Includes JDBC exception handling with an exception hierarchy system.
Spring Architecture and Components
Let's break down the fundamental pieces of a Spring Framework application to help you see the big picture.
Beans
Spring Beans are instances of classes that are managed by Spring. They are the most fundamental component of a Spring program.
Traditionally, objects would create personal instances of their dependencies. Spring manages all the dependencies of an object and instantiates the object into a bean after injecting the required dependencies. The @Component
annotation is the most common method of defining beans.
@Component
public class Vehicle {
}
Beans have a set lifecycle and visibility based on their scope. There are six types of scopes: singleton, prototype, request, session, application, and websocket. The singleton and prototype scopes can be used in any application while the last four scopes are only available for a web application.
The default scope of a bean is singleton, in which only one instance of the bean is created and cached in memory. Multiple requests for the bean return a shared reference to the same bean. In contrast, prototype scope results in the creation of new beans whenever a request for the bean is made to the application context.
Autowiring
Spring's method of injecting beans into one and another. Spring identifies a selected bean's dependency, looks for a match, and then populates the dependency. The @Autowired
annotation tells Spring to find and inject a collaborating bean into another. If more than one bean of the same type is available, Spring throws an error.
In the following scenario, two beans of type Operator are detected by Spring:
@Component
class Arithmetic(){
@Autowired
private Operator operator;
//...
}
@Component
class Addition implements Operator {
}
@Component
class Subtraction implements Operator {
}
IoC Container
An IoC container is a framework that provides the Inversion of Control functionality. The IoC container manages the beans and creates any instances required.
For example, say we have the class Vehicle
that depends on another class, Engine
.
class Vehicle{
private Engine engine;
//...
}
With IoC, the programmer only needs to mention the dependency and Spring will do the rest. The IoC container will create instances of both classes and inject Engine
into Vehicle
as a dependency.
Spring Modules and Spring Projects
Modules are collections of tools grouped by their intended function. Developers can specify which modules beyond the basic set they'd like to import as dependencies for any given application.
Modules are organized in groups called Projects. Each Project contains modules that are specialized for working in a specific platform or application type. The project and module systems help to keep your program lightweight as you can choose to load only the tools used in the application.
The modules of the basic Spring Project architecture are shown below grouped together by their layer:
The Spring Core Container includes the 4 modules essential to use Spring: Beans, Core, Context, and Spring Expression Language (SpEL). These modules are responsible for the fundamental functionality of the Spring framework, like Inversion of Control (IoC), dependency injection, internationalization as well as support for querying the object at run time.
The Spring Data access/integration layer provides support for interacting with databases and managing data. It has 4 main pieces:
- The Java Database Connectivity (JDBC) module, which allows the data layer to get, store, or interface with other systems without needing to write cumbersome standalone JDBC code.
- The Object Relational Mapping (ORM) module, which allows your Spring web application to interface with ORM frameworks.
- The Java Messaging Service (JMS) module, which allows Spring to produce messages of its own and consume messages from other systems. This is essential for reactive apps.
- The Object-XML Mapping (OXM) module, which provides useful features to make object-to-XML file transformation easy.
The Web layer contains the Web, Servlets, Portlets, and Sockets modules used to create web applications.
The Test module addresses the cross-cutting concern of unit testing. The Spring Test framework supports testing with JUnit, TestNG, as well as creating mock objects for testing the code in isolation.
The AOP module provides Aspect-Oriented Programming functionalities like method interception, pointcuts, security, and logging features. Spring has its own module called Spring AOP that offers basic, aspect-oriented programming functionality. Advanced AOP functionality can be implemented through integration with AspectJ. AOP features cross-cutting concerns from business logic.
Outside of this basic project, Spring includes projects for all major use cases. These projects include modules that are too niche for a basic project but include invaluable APIs and functionalities for the target use.
For example, Spring Cloud allows the development of cloud native applications that can be dynamically configured and deployed. It provides functionality for handling common patterns in distributed systems. Other projects include Spring Boot, Spring Security, Spring DAO, Spring Context, and many more.
Keep learning the Spring Framework.
Learn Spring quickly by building live projects that show you how and why to use your new skills. Educative's text-based courses are easy to skim and feature live coding environments to help you get lasting learning at your pace.
The Complete Guide to Spring 5 and Spring Boot 2
Get started with Spring
Now we'll get you some hands-on experience with your first Spring application: a simple movie recommendation system.
Setting up a new project with Spring Framework is difficult because you need to set up the full architecture by hand, including which Apache Maven dependencies to use, whether to use XML or Java, and you must install a web server like Tomcat.
Instead, we'll use the Spring Boot project to automate much of the setup process and use its built-in web server.
How to start your project
We'll use Spring Initializr to create a Spring Boot project fast using its simple selection menu.
First, go to start.spring.io
. You'll find a menu interface like the one below with settings selections and metadata fields.
For this project, we'll select "Maven Project", choose Java as our language, and choose the latest version of Spring Boot. Avoid "SNAPSHOT" versions for now because these are versions being alpha or beta-tested. Under "Project Metadata", enter io.datajek.springbasics
for "GroupID" and movie-recommmender-system
for "ArtifactID. The group ID and artifact ID are basically the package name and class name. You'd normally add module dependencies under "Dependencies", but this project only requires default Spring tools.
Once you've entered everything, press "Generate" to create a zip file with setup architecture. Unzip the folder into the desired location on your hard drive. This folder will contain a pom.xml
file to import into Eclipse IDE.
After a short moment, you'll see the following hierarchy:
-
src/main/java
where the Java code will be written -
src/main/resources
where the application properties are written -
src/test/java
where the tests will be written You can now right-click theMovieRecommenderSystemApplication.java
and run it as a Java application to produce the following console output.
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.4.RELEASE)
2021-05-03 22:46:15.549 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : Starting MovieRecommenderSystemApplication v0.0.1-SNAPSHOT on b041f076fcbd with PID 78 (/Code/movie-recommender-system/target/movie-recommender-system-0.0.1-SNAPSHOT.jar started by root in /Code/movie-recommender-system/target)
2021-05-03 22:46:15.563 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : No active profile set, falling back to default profiles: default
2021-05-03 22:46:16.458 INFO 78 --- [ main] .b.m.d.MovieRecommenderSystemApplication : Started MovieRecommenderSystemApplication in 1.41 seconds (JVM running for 1.855)
Congratulations, you set up your first Spring application with Spring Boot!
Adding a Dependencies
Now, we'll add a simple implementation of the movie recommender using Spring's dependency system. The program will take a movie title as input and return three movie titles of the same genre. For now, we'll be hardcoding our output so you can focus on learning the program's structure.
First, create a new class in src/main/java
named RecommenderImplementation
.
Next, we'll add the recommendMovies
method to RecommenderImplementation
. The recommendMovies
method will take a String movie title as input and return the three recommendations in a String array.
Use the hardcoded implementation below:
public String[] recommendMovies (String movie) {
//use content based filter to find similar movies
//return the results
return new String[] {"M1", "M2", "M3"};
}
Now, create an instance of the RecommenderImplementation
class in the MovieRecommenderSystemApplication
file, then call the recommendMovies
method through the RecommenderImplementation
class.
public static void main(String[] args) {
RecommenderImplementation recommender = new
RecommenderImplementation();
String[] result = recommender.recommendMovies("Finding Dory");
System.out.println(result);
}
Next, we'll implement content-based filtering to find recommendations. To keep recommendMovies
independent of the filtering logic, we'll create a new class called ContentBasedFilter
with a method called getRecommendations
. This method would be where you could implement complex filtering that looks at relevant data like watch history, user-match rating, and so on. Keep these ideas in mind for when you continue expanding this project after the tutorial.
For now, we'll hardcode getRecommendations
to return the same three movies.
public String[] getRecommendations(String movie) {
//logic of content based filter
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
We can now use the methods of the ContentBasedFilter
class in the RecommenderImplementation
class. Replace the previous hardcoded implementation of recommendMovies
with the following dependency-based implementation.
public String[] recommendMovies(String movie) {
ContentBasedFilter filter = new ContentBasedFilter();
String[] results = filter.getRecommendations("Finding Dory");
return results;
}
Finally, we'll add a toString
method to the main
method to make the String array readable as an output.
Your program will now look like this:
package io.datajek.spring.basics.movierecommendersystem.lesson1;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MovieRecommenderSystemApplication {
public static void main(String[] args) {
//SpringApplication.run(MovieRecommenderSystemApplication.class, args);
//create object of RecommenderImplementation class
RecommenderImplementation recommender = new RecommenderImplementation();
//call method to get recommendations
String[] result = recommender.recommendMovies("Finding Dory");
//display results
System.out.println(Arrays.toString(result));
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson1;
public class RecommenderImplementation {
public String [] recommendMovies (String movie) {
//use content-based filter to find similar movies
ContentBasedFilter filter = new ContentBasedFilter();
String[] results = filter.getRecommendations("Finding Dory");
//return the results
//return new String[] {"M1", "M2", "M3"};
return results;
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson1;
public class ContentBasedFilter {
public String[] getRecommendations(String movie) {
//implement logic of content-based filter
//return movie recommendations
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
}
The current implementation is tightly coupled because the RecommenderImplementation
class depends on ContentBasedFilter
to work. Now, we'll decouple these components to allow for multiple types of filtering, such as a CollaborativeFilter
. We'll use an abstract Filter
interface with different implementations based on the selected filter type.
Spring makes this easy by automatically creating and managing the dependent instances for each component. It will automatically detect the dependency relationship between our classes, meaning you can focus on the code.
Your decoupled project will look like this:
package io.datajek.spring.basics.movierecommendersystem.lesson2;
import java.util.Arrays;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MovieRecommenderSystemApplication {
public static void main(String[] args) {
//SpringApplication.run(MovieRecommenderSystemApplication.class, args);
//passing name of the filter as constructor argument
RecommenderImplementation recommender = new RecommenderImplementation(new ContentBasedFilter());
//call method to get recommendations
String[] result = recommender.recommendMovies("Finding Dory");
//display results
System.out.println(Arrays.toString(result));
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class CollaborativeFilter implements Filter{
public String[] getRecommendations(String movie) {
//logic of content based filter
return new String[] {"Finding Nemo", "Ice Age", "Toy Story"};
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class ContentBasedFilter implements Filter{
public String[] getRecommendations(String movie) {
//implement logic of content-based filter
//return movie recommendations
return new String[] {"Happy Feet", "Ice Age", "Shark Tale"};
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public class RecommenderImplementation {
//use filter interface to select filter
private Filter filter;
public RecommenderImplementation(Filter filter) {
super();
this.filter = filter;
}
//use a filter to find recommendations
public String [] recommendMovies (String movie) {
//print the name of interface implementation being used
System.out.println("Name of the filter in use: " + filter + "\n");
String[] results = filter.getRecommendations("Finding Dory");
return results;
}
}
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public interface Filter {
public String[] getRecommendations(String movie);
}
Advanced Spring concepts to learn next
Congratulations on completing your first decoupled Spring application! As you continue learning more advanced Spring concepts, try returning to this project and implementing more intricate filters and features. This will help you solidify your learning and give you a portfolio-ready project by the time you're ready to interview.
Some new concepts to apply to this project are:
- Implement advanced autowiring
- Optimize resource management with bean scope
- Convert to a web application using Spring Web MVC framework
- Create self-repairing systems using the BeanFactory design pattern
- Add relational database support with Hibernate templates and Java Persistence API (JPA)
To help you learn these concepts and apply them to this project, Educative has created The Complete Guide to Spring 5 and Spring Boot 2. This course walks you through all the advanced features of Spring Framework and shows you how to use each in a project setting. By the end, you'll have hands-on experience with all of these topics and have the Spring context you need to thrive in an interview.
Continue reading about Spring and Java
Posted on May 5, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.