A Closer Look at Spring Boot
A Closer Look at Spring Boot
Want to take a closer look at at the Spring Boot architecture? Check out this post to learn more about the features and advantages to using Spring Boot for your projects/
Join the DZone community and get the full member experience.Join For Free
With the advent of microservices architecture and cloud computing, there is an increasing need for a new approach to artifact deployment: a standalone Java application.
In very little time, Spring Boot has become a leading technology in this fields.
Its strengths include:
- Opinionated view — it means it does a lot of job in your place;
- An extremely quick project startup: dependencies are grouped by subject into so-called "starters"
- Executable jar: the artifact produced is an executable JAR (or better an Uber JAR);
My Opinion on Spring Boot
From my point of view, this is an example of “Inversion of Control" implementation — usually, you choose a set of libraries and then try to configure them to work together, but in this case, you left control to the framework that takes care of configuration.
When the application starts, the framework detects dependencies on the classpath and tries to configure it. For example, when Spring Boot detects a Hibernate jar on the classpath, it configures a datasource for you, or when the Spring MVC jar is found, it configures a Dispatcher Servlet. Enabling autoconfiguration is extremely easy; just annotate your main configuration class with auto configuration, which is enabled by annotating your main class with
All logic needed for autoconfiguring your application is handled by the spring-boot-autoconfigure library, which contains all classes that are packaged to perform logic for a particular configuration.
In addition, an extreme “convention over configuration” approach is implemented to customize almost every aspect of autoconfiguration by providing a file named
application.yaml) on the classpath.
In this file, you can control a specific aspect of autoconfiguration as the server port:
And, exclusion is shown below:
Quick Project Startup
Most of the time, to start a Spring Boot project, you just go to start.spring.io, choose the technologies that you want to use, and then download a zip file with your project structured as a Maven or Gradle project.
Notice that I wrote “technologies” and not “libraries;” this is because you can say: “I want a web application with security and JPA” and Spring will choose the right libraries for you.
In my opinion, the most extraordinary thing is not the fact that is so easy to start a project but the way in which Spring accomplishes this in such an elegant way.
The idea is to group a set of useful and focused libraries into a multi-module project and then include it as a dependency.
For example, when you choose the “Web” option, start.spring.io adds:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
This is just a multi-module project that collects all libraries needed to run a web application included an embedded Tomcat:
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> </dependency>
One of the most noticeable benefits to this approach is that you do not have to worry about library version compatibility — starters come with this as a guarantee.
Putting together configuration detection and starters, the only thing that is missing is a more convenient way to distribute the artifact. Spring Boot addresses this by packaging the whole project as an Uber JAR.
An Uber JAR is a regular JAR in which all dependencies needed are included. This is done using:
spring-boot-maven-plugin: you can find it in the plugins section of the pom;
maven-shade-plugin: it’s provided by
spring-boot-starter-parentand it creates the effective Uber Jar.
The maven-shade-plugin, in particular, takes care of packaging dependencies and configure —through transformers — specific files like:
- Service provider configuration files into
META-INF\servicesthat are handled by
A list of transformers with their description can be found here.
The following is an example of a Spring Boot Loader-compatible JAR structure:
+-META-INF | +-MANIFEST.MF +-org | +-springframework | +-boot | +-loader | +- Main-Class +-BOOT-INF +-classes | +- Start-Class +-lib +-dependency.jar
To make it executable, the META-INF\MANIFEST.MF file is initialized with the following properties:
Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.yourcompany.MainCOnfigurationCLass Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/
When the application is launched — with the java -jar application.jar —
META-INF\MANIFEST.MF is read. In here, org.springframework.boot.loader.JarLauncher is loaded as a main class — its job is to load the following:
- Libraries collected into
- Application classes collected into
BOOT-INF\classes contains the Start-Class – the one annotated with
@SpringBootApplication – that actually bootstraps and launches the Spring application.
Spring Boot is an extraordinary example of a well-done architecture: it accomplishes specific tasks, uses modern approaches, and proposes a solution to all the hot topics.
If someone finds Spring Boot too restrictive, that is because its power is in its configuration discovering and its dependencies' management — this can force users to lose control. For example, it is not an easy task to use a different parent POM instead of spring-boot-starter-parent.
In my opinion, Spring Boot must be seen as a framework intended as a standardized collection of tools and not as a utility library. You don't use Spring Boot. You create a Spring Boot-oriented application (that is a native cloud Java application).
If you think in this way, then you can enjoy the Spring Boot way to do things and get the most from it! Happy coding!
Opinions expressed by DZone contributors are their own.