Search icon CANCEL
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Building Web Apps with Spring 5 and Angular

You're reading from   Building Web Apps with Spring 5 and Angular Modern end-to-end web application development

Arrow left icon
Product type Paperback
Published in Aug 2017
Publisher Packt
ISBN-13 9781787284661
Length 370 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Ajitesh Kumar Shukla Ajitesh Kumar Shukla
Author Profile Icon Ajitesh Kumar Shukla
Ajitesh Kumar Shukla
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Introduction to Spring Web Framework 2. Preparing the Spring Web Development Environment FREE CHAPTER 3. Data Access Layer with Spring and Hibernate 4. Testing and Running Spring Web App 5. Securing Web App with Spring Security 6. Getting Started with Angular 7. Creating SPA with Angular and Spring 5 8. Unit Testing with Angular Apps 9. Securing an Angular App 10. Integrating Angular App with Spring Web APIs 11. Deploying the Web Application

Introduction to the Spring IOC container

As a primer to learning the Spring Web MVC framework, it is recommended to learn some of the following object-oriented design principles, which act as a basis for the Spring Web framework. Note that these principles form a part of the famous Single responsibility, Open-closed, Liskov substitution, Interface segregation, and Dependency inversion (SOLID) principle by Robert Martin (Uncle Bob):

  • Single Responsibility Principle (SIP): This principle states that a module, a class, or a method should have the responsibility of serving just one functionality of the underlying software. In other words, a module, a class or a method should have just one reason to change. Modules or classes following SIP have high cohesiveness, and thus, can be termed as reusable entities. Classes violating SIP are found to have high cyclomatic complexity, and thus, low testability.
  • Open-Closed Principle (OCP): This principle states that the classes are open for extension, but closed for modification. Based on this principle, the core classes of the Spring Web MVC consist of some methods which are marked as final, which, essentially, means that these final methods can not be overridden with custom behavior.
  • Liskov Substitution Principle (LSP): This principle states that if a class A (child class) is derived from class B (parent class), then the object of class B can be replaced by (or substituted with) an object of class A without changing any of the properties of class B. It can be inferred that the functions which use references of the base class must be able to use objects of the derived class without the need to know about the implementation of the base class. For example, let's consider the square and rectangle example. In the case where square derives from rectangle, then, as per LSP, an object of the class Rectangle can be substituted with an object of the class Square. However, in reality, this is not possible without doing appropriate implementation in the Square class setter methods, where setting either of length or breadth sets another side of equal length, and/or code using these classes do appropriate checks to find out whether the object is an instance of the class Square or Rectangle.
  • Interface Segregation Principle (ISP): This principle states that the fat interfaces having large number of API definitions should be split into smaller interfaces defining a set of cohesive APIs. Not following this principle leads to the client providing empty implementations for unwanted APIs.
  • Dependency Inversion Principle (DIP): This principle is pretty much related to the IOC principle, which is discussed in the next section. It states that the dependency relationship between higher-level modules with low-level modules is reversed, thus making these modules independent of each other's implementation details.

Before we get into understanding what is Spring IOC Container, let us quickly learn what is IOC. 

What is IOC?

Many a times, the Hollywood principle of Don't call us, we will call you is used to explain the concept of Inversion of Control. In Hollywood, this is what one gets to hear after auditioning is done. If we apply this principle to the programming model, instead of the classes creating dependencies along with serving functionality, the dependencies are appropriately made available to the classes during runtime, and the classes just need to focus on delivering the functionality.

Simply speaking, Inversion of Control (IOC) is about inverting the flow of control that the traditional programming model used to have in terms of objects at the higher-level handling the creation and management of lower-level objects' (can also be termed as dependencies) life cycle. In the IOC programming model, higher-level objects rather receive one or more instances of these dependencies from the calling object or external framework. This is why IOC is also termed Dependency Injection, wherein the dependencies are injected appropriately, and, objects bother themselves solely with the program execution and not with the object creation. Inversion of Control is related to the object-oriented principle known as the Dependency Inversion Principle (DIP), coined by Robert Martin (Uncle Bob).

Let's take a look at the following code sample, which represents higher-level objects handling the creation of lower-level objects (dependencies):

    /*
* This class demonstrates the dependency of higher-level object
* (DrawWithoutIOC)
* onto lower level objects such as Rectangle, Square which are
* created within
* Shape class based on the value of shapeType which is passed as a
* method
* parameter to draw method.
*/

public class DrawWithoutIOC {

Logger logger = Logger.getLogger(DrawWithoutIOC.class.getName());

public void draw(String shapeType) {
Shape shape = new Shape();
try {
shape.draw(shapeType);
}
catch (UndefinedShapeException e) {
logger.log(Level.INFO, e.getMessage(), e);
}
}
/*
* Note that Shape class creates instances of Rectangle or Square
class
* based on the value of shapeType. Any new value that needs to be
supported requires change in the draw method of Shape class.
*/

private class Shape {
public void draw(String shapeType) throws
UndefinedShapeException
{
if(shapeType.equals("rectangle")) {
Rectangle rectangle = new Rectangle();
rectangle.draw();
} else if(shapeType.equals("square")) {
Square square = new Square();
square.draw();
} else {
String shapeNotSupportedMessage = "Shape " + shapeType + "
not supported";
logger.log(Level.INFO, shapeNotSupportedMessage);
throw new UndefinedShapeException
(shapeNotSupportedMessage);
}
}
}

public static void main(String[] args) {
DrawWithoutIOC drawWithoutIOC = new DrawWithoutIOC();
drawWithoutIOC.draw("circle");
}
}

Let us take a look at the class DrawWithIOC, which accepts the implementation of the Shape object in its public constructor. Note that the dependencies, such as different implementations of the Shape object, are rather injected, and code just does the execution of business logic without bothering about creation of objects related to the different implementations of Shape. Other alternatives to injecting the dependencies are passing arguments to a factory method of the class, or through properties that are set on the object instance:

    /**
* In this class, the Shape is passed as parameter to DrawWithIOC
* constructor.
* draw method on a DrawWithIOC object just invokes the draw method
* on Shape object.
* It, no longer, manage the creation of Shape object based on
* shapeType and there upon, invoke the draw method.
**/

public class DrawWithIOC {
Logger logger = Logger.getLogger(DrawWithIOC.class.getName());

private Shape shape;

public DrawWithIOC(Shape shape) {
this.shape = shape;
}

public void draw() {
this.shape.draw();
}

public static void main(String[] args) {
Shape shape = new Rectangle();
DrawWithIOC drawWithIOC = new DrawWithIOC(shape);
drawWithIOC.draw();
}
}

What is a Spring IOC container?

A Spring IOC container is a framework which, basically, manages the life cycle of plain old Java objects (POJOs), and injects them into the application as required. Java objects define their dependencies using one of the following methods:

  • Dependencies are passed as arguments to the constructor method of the object. See how the object is passed as an argument to the constructor method in the example cited in the previous section.
  • Dependencies are passed as arguments to the setter method of the object.
  • Dependencies are passed as arguments to a factory method of the object.

A Spring IOC container injects the dependencies after it creates the beans. Note the fact that dependencies are no longer managed by Java objects. They are rather managed and injected by the framework, and hence, Inversion of Control.

The following are the packages which are core to the IOC container:

  • org.springframework.beans
  • org.springframework.context

It is the interface, org.springframework.context.ApplicationContext (sub-interface of the interface, BeanFactory), which represents the Spring IOC container and is responsible for managing the life cycle of beans. The instructions related to creating, configuring, and assembling the objects is termed Configuration Metadata. The configuration metadata is often represented using Java annotations or XML. A Java application using Spring IOC Container is created by combining Business POJOs with the previously mentioned configuration metadata, and passing it on to the IOC Container (an instance of ApplicationContext). The same is represented using the following diagram:

Figure 1: Java Application with Spring IOC Container

Let's illustrate the preceding diagram with an example. The following code represents how a service, namely, UserService is instantiated using Spring IOC container in a Spring Boot web application. Notice how the annotation-based autowiring feature has been used to have ApplicationContext autowired to the userService field in this code:

    package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.services.UserService;
import com.services.domain.User;

@Controller
@SpringBootApplication (scanBasePackages={"com.services"})
public class DemoApplication {

@Autowired
private UserService userService;


@RequestMapping("/")
@ResponseBody
String home() {
User user = null;
return "Hello " + userService.getUsername(user) + ". How are you?";
}

public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at €18.99/month. Cancel anytime