Spring Framework Tutorial: Getting Started with Spring

ryanthelin

Ryan Thelin

Posted on May 5, 2021

Spring Framework Tutorial: Getting Started with Spring

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:

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 {
}
Enter fullscreen mode Exit fullscreen mode

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 {

}
Enter fullscreen mode Exit fullscreen mode

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;
    //...
}
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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.

Alt Text

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 the MovieRecommenderSystemApplication.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)
Enter fullscreen mode Exit fullscreen mode

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.

Alt Text

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"};
}
Enter fullscreen mode Exit fullscreen mode

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);
}
Enter fullscreen mode Exit fullscreen mode

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"};
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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));
    }
}
Enter fullscreen mode Exit fullscreen mode
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;
    }
}
Enter fullscreen mode Exit fullscreen mode
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"};
    }
}
Enter fullscreen mode Exit fullscreen mode

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));
    }
}
Enter fullscreen mode Exit fullscreen mode
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"};
    }
}
Enter fullscreen mode Exit fullscreen mode
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"};
    }
}
Enter fullscreen mode Exit fullscreen mode
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;
    }
}
Enter fullscreen mode Exit fullscreen mode
package io.datajek.spring.basics.movierecommendersystem.lesson2;
public interface Filter {
    public String[] getRecommendations(String movie);
}
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
ryanthelin
Ryan Thelin

Posted on May 5, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related