What Spring Boot Is & Your First App
If you've heard Spring described as "the heavyweight enterprise Java thing with a thousand XML files," that reputation was earned — about fifteen years ago. Spring Boot is the answer the Spring team built to that exact pain. This phase is about getting the mental model straight before you write a line of code, because the single biggest thing that confuses newcomers isn't the syntax — it's not understanding what the framework is doing on your behalf. Once you can see the machinery, Boot stops feeling like magic and starts feeling like a very well-organized assistant.
We'll untangle Spring from Spring Boot, demystify the famous "auto-configuration," meet starters, and then stand up a real web app you can hit in a browser. By the end you'll have a running server and a clear picture of everything Boot quietly did so you didn't have to.
This guide assumes you're comfortable with Java classes, methods, and annotations. If public class, @Override, and new aren't second nature yet, spend a little time in /guides/java-from-zero first. It also builds directly on the framework mental model from /guides/what-a-framework-even-is — we'll lean on that idea of inversion of control more than once.
The mental model: Spring is the toolbox, Boot is the toolbox pre-assembled
Here's the distinction that clears up half the confusion people have, so let's plant it firmly.
📝 Spring (the Framework) is a huge collection of tools for building Java applications: an IoC container that constructs and connects your objects, Spring MVC for handling web requests, Spring Data for talking to databases, Spring Security for auth, and a lot more. It's powerful and flexible — and historically, that flexibility meant you had to configure every piece by hand, often in long XML files, before anything would run.
📝 Spring Boot is Spring with three things added on top: auto-configuration (Boot wires up sane defaults for you), sensible defaults (it picks reasonable settings so you don't have to specify everything), and an embedded server (a web server lives inside your app, so there's nothing separate to install and deploy to). The one-line version:
💡 Key point. Boot doesn't replace Spring — it is Spring, with the boilerplate already filled in. Think of Spring as a kitchen full of professional equipment, and Spring Boot as that same kitchen with the oven preheated, the knives sharpened, and a recipe on the counter. Same tools. You just start cooking instead of assembling.
So whenever someone says "I'm using Spring Boot," they're using Spring. Boot is the on-ramp.
Auto-configuration, demystified
Auto-configuration is the part that feels like sorcery, so let's pull the curtain back, because it's the single most important idea in this whole guide.
📝 Auto-configuration is Boot looking at what's on your project's classpath — the set of libraries your app has available — and configuring those libraries with reasonable defaults, automatically, at startup. Add the library that does web stuff, and Boot notices and sets up a web server and JSON handling. Add a database driver, and Boot notices and sets up a connection to the database.
The crucial thing to internalize:
💡 Key point. Auto-configuration is conditional configuration, not guesswork. Under the hood it's a pile of rules shaped like "if the H2 database library is present and the developer hasn't already defined a database connection, then configure an in-memory H2 database." Boot ships hundreds of these
@Conditionalrules. Each one only fires when its conditions are met. Nothing happens by spooky action — every default is a rule you could read.
That conditional design is also why auto-configuration never traps you. Every rule includes a condition like "...and the developer hasn't configured this themselves." The moment you define a piece of configuration, Boot's rule for that piece backs off and lets yours win.
⚠️ Gotcha — "magic" you can't see is still magic to you. The convenience is real, but a default you didn't choose is a default you might not know about. When something behaves unexpectedly (a port, a JSON format, a database that "appeared"), the cause is almost always an auto-configuration default. Learning to ask "what did Boot auto-configure here?" is a core Spring Boot skill — and Boot can print exactly what it decided. We'll come back to that.
The trigger for all this convenience is wonderfully simple: you add a starter.
Starters: curated bundles for one job
You don't hand-pick fifteen libraries and pray their versions are compatible. You add one starter.
📝 A starter is a curated bundle of dependencies for a single job, published by the Spring team with versions that are known to work together. spring-boot-starter-web is the bundle for building web apps — pull it in and you get Spring MVC, an embedded Tomcat server, JSON support (via Jackson), and validation, all in one line. There are starters for data access, security, testing, messaging, and dozens more.
Here's what adding the web starter looks like in a Maven pom.xml:
org.springframework.boot
spring-boot-starter-web
What just happened: you declared a single dependency, and behind it sits an entire stack — the web framework, the server, the JSON serializer, the validator — with mutually compatible versions chosen for you. You did not list Tomcat, Jackson, or Spring MVC individually, and you did not pin any version numbers (Boot's parent project manages those). One line in, and there's now enough on the classpath for auto-configuration to spring into action and stand up a working web server.
💡 Insight. This is the loop that is Spring Boot: you add a starter → that starter puts libraries on the classpath → auto-configuration sees them and wires sane defaults. Almost everything you'll do in Boot is some version of "add the right starter, let Boot configure it, override the bits you care about." Hold onto that sentence — the rest of this guide is just it, in detail.
Your first app
Enough theory. Let's build something that runs. The fastest way to start a Boot project is Spring Initializr.
📝 Spring Initializr (at start.spring.io) is a web page that generates a ready-to-run Boot project for you. You pick your build tool (Maven or Gradle), your Java version, and which starters you want, then download a zip with the folder structure, build file, and a main class already in place. It's the official "new project" button for Spring Boot.
Go to start.spring.io, choose Maven, add the Spring Web dependency (that's spring-boot-starter-web), and generate. Unzip it, and the heart of what you get is one small class:
What just happened: this is the entry point of your whole application. Your normal Java main method is still here — Boot didn't invent a new way to start a program — but instead of your code doing the work, it calls SpringApplication.run(...) and hands control to Spring. That one call boots the framework: it creates the IoC container, runs auto-configuration, finds your code, and starts the embedded server. This is the inversion of control from /guides/what-a-framework-even-is in the flesh — main is the last moment your code is in charge. After run(...), the framework drives and calls back into your code when it needs you.
The one annotation doing the heavy lifting is @SpringBootApplication. It looks innocent, but it's three annotations bundled into one:
📝 @SpringBootApplication combines:
@SpringBootConfiguration— marks this class as a source of bean/config definitions.@EnableAutoConfiguration— turns on the auto-configuration machinery we just discussed.@ComponentScan— tells Spring to scan this package and everything below it for your components (controllers, services, and so on) and register them automatically.
⚠️ Gotcha — package placement matters. Because @ComponentScan searches downward from the package of your main class, anything you write needs to live in that package or a sub-package. A controller dropped into a sibling or parent package won't be found, and you'll get a confusing 404 with no obvious cause. Keep your code under the main class's package and this never bites you.
Now let's add something to actually respond to a request. Create a class next to DemoApplication:
What just happened: @RestController tells Spring "this class holds web request handlers, and whatever they return is the HTTP response body." @GetMapping("/") maps HTTP GET requests for the root URL to the hello() method. You didn't write any code to open a socket, parse the incoming request, match the URL, or format the response — you described which URL runs which method, and the framework owns everything around it. That's routing and handlers, exactly the framework anatomy from the previous guide, wearing Spring's clothes.
Run it from the project folder. Boot projects ship with a wrapper script so you don't even need Maven installed globally:
You'll see Boot start up and announce the embedded server:
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.x.x)
INFO Starting DemoApplication using Java 21
INFO Tomcat initialized with port 8080 (http)
INFO Tomcat started on port 8080 (http) with context path '/'
INFO Started DemoApplication in 1.42 seconds
What just happened: read that output as a receipt of everything Boot did. It started Tomcat — a full web server — inside your process, on port 8080, without you installing or configuring a server anywhere. Now open a browser to http://localhost:8080 and you'll see Hello from Spring Boot!. A real HTTP server, serving your code, from a project you generated minutes ago.
What you didn't have to do
Step back and count what you didn't write, because the gap is the entire value proposition:
- No server install or setup. Tomcat came embedded via the web starter and started itself. There's no separate server to download, configure, or deploy a
.warfile into. - No JSON wiring. Return an object from a controller and Boot serializes it to JSON automatically (Jackson, auto-configured). You'll lean on this constantly.
- No manual object wiring — yet. The IoC container built and connected the objects in your app. We've only scratched this; it's the whole of Phase 2: Dependency Injection & Beans.
- No version juggling. The starter and Boot's parent picked compatible library versions, sidestepping the "dependency hell" that plagued old-school Spring.
- No boilerplate config files. No XML, no manual server descriptors. Sensible defaults covered it.
Here's the whole loop as one picture:
flowchart LR
A[Add spring-boot-starter-web] --> B[Libraries land on classpath]
B --> C[Auto-configuration fires]
C --> D[Embedded Tomcat + MVC + JSON wired]
D --> E[Running app on :8080]
That convenience is the payoff — and the thing to stay aware of. Every box in that diagram is a place Boot made a decision for you. Most of the time those decisions are exactly right, which is why Boot is a joy to start with. But the engineers who are great with Spring Boot are the ones who can name what's in each box when they need to: which server, which defaults, which auto-configuration rules fired.
💡 Insight — make the magic visible. Boot can tell you exactly what it auto-configured. Set the property debug=true (in application.properties) and on startup it prints an auto-configuration report listing every rule that matched and every rule that didn't, with the reason. When something behaves in a way you didn't ask for, that report is where you go to turn "magic" into "oh, that's why." You don't need it today — but knowing it exists is the difference between trusting the framework blindly and understanding it.
Recap
- Spring is the toolbox; Spring Boot is that toolbox pre-assembled — Boot is Spring plus auto-configuration, sensible defaults, and an embedded server. It doesn't replace Spring; it removes the boilerplate.
- Auto-configuration is conditional configuration, not magic. Boot reads your classpath and applies hundreds of "if this library is present and you haven't configured it yourself, then set up this default" rules. The moment you configure something, Boot's default steps aside.
- Starters are curated dependency bundles for one job.
spring-boot-starter-webbrings Spring MVC, embedded Tomcat, and JSON support in a single line with versions chosen for you. - The core loop: add a starter → libraries hit the classpath → auto-configuration wires sane defaults you can override.
@SpringBootApplication= config +@EnableAutoConfiguration+@ComponentScan, andSpringApplication.run(...)is where your code hands control to the framework — inversion of control, live.- Stay aware of the defaults. The convenience is real, but
debug=trueprints the auto-configuration report so the "magic" is always something you can read.
Quick check
Test the mental model before moving on:
[
{
"q": "What is the key difference between Spring and Spring Boot?",
"choices": [
"Spring Boot is a different framework that replaces Spring entirely",
"Spring Boot is Spring with auto-configuration, sensible defaults, and an embedded server added on top",
"Spring is for web apps and Spring Boot is for desktop apps",
"Spring Boot removes the IoC container that Spring uses"
],
"answer": 1,
"explain": "Spring Boot doesn't replace Spring — it IS Spring, with the boilerplate pre-filled via auto-configuration, sensible defaults, and an embedded server."
},
{
"q": "How does auto-configuration decide what to set up?",
"choices": [
"It asks you a series of questions when the app starts",
"It configures every possible feature whether you use it or not",
"It looks at what libraries are on the classpath and applies conditional rules, backing off when you've configured something yourself",
"It reads a mandatory XML file you must write by hand"
],
"answer": 2,
"explain": "Auto-configuration is conditional: 'if this library is present and you haven't configured it yourself, then apply this default.' Your own config always wins."
},
{
"q": "What three annotations does @SpringBootApplication bundle together?",
"choices": [
"@RestController, @GetMapping, and @Service",
"@Configuration, @EnableAutoConfiguration, and @ComponentScan",
"@Autowired, @Bean, and @Component",
"@SpringBootTest, @Profile, and @Value"
],
"answer": 1,
"explain": "@SpringBootApplication combines @SpringBootConfiguration (a form of @Configuration), @EnableAutoConfiguration (turns on auto-config), and @ComponentScan (finds your components)."
}
]
Guide overview · Phase 2: Dependency Injection & Beans →
Check your understanding
1. What is the key difference between Spring and Spring Boot?
2. How does auto-configuration decide what to set up?
3. What three annotations does @SpringBootApplication bundle together?