Your First Spring Boot Application
A single @SpringBootApplication annotation is all it takes to launch the entire application—the magic of Spring Boot lies in the ingenious combination of three annotations.
1. What You'll Learn
@SpringBootApplicationPrinciples of Annotation Decomposition and Combination- Main Startup Class
main()Methods andSpringApplication.run()Execution Flow application.propertiesvsapplication.ymlConfiguration File Formats- Customizing the Spring Boot Banner and Interpreting Startup Logs
- Run the first "Hello OrderFlow" interface
2. A True Story About a New Project
(1) Pain Point: It takes half a day to set up a project
Alice recalled her experience using traditional Spring MVC when she first started out: creating a project required configuring web.xml, applicationContext.xml, and spring-mvc.xml, as well as installing Tomcat and configuring the JNDI data source. Just getting the project up and running took half a day, not to mention debugging startup order and bean loading issues.
(2) The Spring Boot Solution
Spring Boot requires just one annotation and one main method:
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
(3) Revenue
Alice used Spring Boot to create the OrderFlow project. It took her just 5 minutes to go from scratch to her first API response—no XML required, no external container needed, and the startup logs were clear and easy to read.
3. Breaking Down the @SpringBootApplication Annotation
(1) A combination of three annotations
@SpringBootApplication is a composite annotation equivalent to using the following three annotations simultaneously:
graph TB
A["@SpringBootApplication"] --> B["@SpringBootConfiguration"]
A --> C["@EnableAutoConfiguration"]
A --> D["@ComponentScan"]
B --> B1["Marks class as<br/>Configuration bean source"]
C --> C1["Triggers auto-configuration<br/>based on classpath"]
D --> D1["Scans components<br/>in same package tree"]
| Annotation | Function | Equivalent Traditional Notation |
|---|---|---|
@SpringBootConfiguration |
Mark the current class as a configuration class | @Configuration |
@EnableAutoConfiguration |
Enable Auto-Configuration | @EnableAutoConfiguration |
@ComponentScan |
Component Scan | <context:component-scan> |
(2) @ComponentScan scanning rules
@ComponentScan By default, the scan covers the package containing the main launch class and all its subpackages.
com.orderflow ← The package containing the main launch class
├── OrderFlowApplication.java ← @SpringBootApplication
├── controller/ ← Scanned by @ComponentScan
│ └── OrderController.java
├── service/ ← Scanned by @ComponentScan
│ └── OrderService.java
└── repository/ ← Scanned by @ComponentScan
└── OrderRepository.java
com.other ← ⚠️ Not included in the scan!
4. SpringApplication.run() Startup Process
(1) Startup Sequence
The execution process of SpringApplication.run() is a carefully designed pipeline:
sequenceDiagram
participant Main as main()
participant SA as SpringApplication
participant Ctx as ApplicationContext
participant Bean as Beans
Main->>SA: new SpringApplication()
SA->>SA: infer Primary Sources
SA->>SA: check Web Application Type
SA->>SA: load Initializers & Listeners
Main->>SA: run(args)
SA->>SA: create Bootstrap Context
SA->>SA: prepare Environment
SA->>SA: print Banner
SA->>Ctx: create ApplicationContext
SA->>Ctx: prepare Context (register sources)
SA->>Ctx: refresh Context
Ctx->>Bean: instantiate Beans
Ctx->>Bean: auto-configure
SA->>SA: call Runners
SA->>Main: return ApplicationContext
(2) Determining the Web Application Type
Spring Boot Automatically Detects Application Type:
| Condition | Type | Container Used |
|---|---|---|
classpath contains spring-webmvc |
SERVLET | Tomcat / Jetty / Undertow |
classpath contains spring-webflux but not spring-webmvc |
REACTIVE | Netty |
| None | NONE | No embedded containers |
(1) ▶ Example: Customizing SpringApplication Startup
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(OrderFlowApplication.class);
app.setBannerMode(Banner.Mode.CONSOLE);
app.setWebApplicationType(WebApplicationType.SERVLET);
app.run(args);
}
}
Output:
// Execution Successful
5. Configuration File Format
(1) Properties vs. YAML
Spring Boot supports two configuration file formats that are functionally equivalent but differ in syntax.
(1) ▶ Example: How to write application.properties
server.port=8080
spring.application.name=orderflow-service
spring.datasource.url=jdbc:mysql://localhost:3306/orderflow
spring.datasource.username=root
spring.datasource.password=secret
spring.jpa.hibernate.ddl-auto=update
Output:
// Execution Successful
(2) ▶ Example: How to write application.yml
server:
port: 8080
spring:
application:
name: orderflow-service
datasource:
url: jdbc:mysql://localhost:3306/orderflow
username: root
password: secret
jpa:
hibernate:
ddl-auto: update
Output:
The configuration has taken effect.
| Dimension | Properties | YAML |
|---|---|---|
| Hierarchical Structure | Separated by . |
Indentation Indicates Hierarchy |
| Readability | Simple key-value pairs, flat | Clear hierarchy, suitable for nesting |
| List Support | list[0]=a |
- a More Intuitive |
| Repeated prefix | Must be repeated | Shared prefix at the same level |
| Parsing Performance | Faster | Slightly slower (requires parsing hierarchy) |
| Priority | Same | Same (properties take precedence when both exist) |
(2) Quick Reference for Common Configuration Options
| Configuration Option | Default Value | Description |
|---|---|---|
server.port |
8080 | Application Listening Port |
spring.application.name |
— | App Name |
server.servlet.context-path |
/ | Contextual path |
spring.main.banner-mode |
console | Banner Display Mode |
spring.jpa.show-sql |
false | Print SQL |
logging.level.root |
INFO | Global Log Level |
6. Customizing the Banner and Startup Logs
(1) Custom Banner
Place a custom banner in src/main/resources/banner.txt so that it automatically displays when Spring Boot starts.
(1) ▶ Example: OrderFlow Custom Banner
____ _ ____ __
/ ___| _ __ __ _| |_ ___ / ___|| | ___ _ __
| | | '_ \ / _` | __/ _ \ \___ \| |/ _ \| '_ \
| |___ | | | | (_| | || __/ ___) | | (_) | | | |
\____||_| |_|\__,_|\__\___| |____/|_|\___/|_| |_|
:: OrderFlow Service :: v${application.version:1.0.0}
:: Spring Boot ${spring-boot.version} ::
Output:
Execution Successful
(2) Interpreting the Startup Log
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | / / / /
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v3.2.5)
2024-01-15 10:00:01.123 INFO 12345 --- [main] c.o.OrderFlowApplication : Starting OrderFlowApplication
2024-01-15 10:00:03.456 INFO 12345 --- [main] o.s.b.w.e.t.TomcatWebServer : Tomcat initialized with port 8080 (http)
2024-01-15 10:00:04.789 INFO 12345 --- [main] o.s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories
2024-01-15 10:00:06.012 INFO 12345 --- [main] c.o.OrderFlowApplication : Started in 5.123 seconds
| Log Keywords | Meaning |
|---|---|
Starting OrderFlowApplication |
App launching |
Tomcat initialized with port |
Starting Embedded Tomcat |
Bootstrapping Spring Data JPA |
Automatically Configure the JPA Repository |
Started in X seconds |
Startup complete, took |
7. Run Your First "Hello OrderFlow" Interface
(1) ▶ Example: Hello OrderFlow Controller
package com.orderflow.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
public class HelloController {
@GetMapping("/api/hello")
public Map<String, String> hello() {
return Map.of(
"message", "Hello, OrderFlow!",
"timestamp", java.time.Instant.now().toString()
);
}
}
Output:
HTTP 200 OK
Content-Type: application/json
{"status":"success","data":{}}
$ curl http://localhost:8080/api/hello
{"message":"Hello, OrderFlow!","timestamp":"2024-01-15T10:00:00Z"}
(2) ▶ Example: Using @Value for configuration injection
@RestController
public class HelloController {
@Value("${spring.application.name}")
private String appName;
@GetMapping("/api/info")
public Map<String, String> info() {
return Map.of(
"application", appName,
"javaVersion", System.getProperty("java.version")
);
}
}
Output:
// Execution Successful
8. Comprehensive Example: Complete OrderFlow Startup Configuration
// src/main/java/com/orderflow/OrderFlowApplication.java
package com.orderflow;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
// src/main/java/com/orderflow/controller/OrderFlowController.java
package com.orderflow.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Instant;
import java.util.Map;
@RestController
public class OrderFlowController {
@Value("${spring.application.name:orderflow}")
private String appName;
@GetMapping("/api/health")
public Map<String, Object> health() {
return Map.of(
"status", "UP",
"application", appName,
"timestamp", Instant.now()
);
}
}
# src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: orderflow-service
$ curl http://localhost:8080/api/health
{"status":"UP","application":"orderflow-service","timestamp":"2024-01-15T10:00:00Z"}
❓ FAQ
properties and YAML coexist?properties definition takes precedence. It is recommended to use only one to avoid confusion. We recommend YAML, as it offers a clearer hierarchy.spring.main.banner-mode=off in the configuration file, or app.setBannerMode(Banner.Mode.OFF) in the code.server.port=8081, or locate and terminate the process using the port: lsof -i :8080 (Linux/Mac) or netstat -ano | findstr 8080 (Windows).ddl-auto=validate causes slow connections to remote databases; 3) Unnecessary auto-configurations have not been excluded. Use --debug mode to view details.<mainClass> in the Maven plugin; run the class containing the main method directly in the IDE; the Spring Boot Maven Plugin will automatically detect it during packaging.📖 Summary
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan- The main startup class should be placed in the root package to ensure that the component scan covers all subpackages.
SpringApplication.run()Walk through the complete process of setting up the environment → creating a context → refreshing → instantiating a bean- YAML and Properties are functionally equivalent; YAML has a clearer hierarchy, while Properties are parsed faster.
- Customize the banner using
banner.txt; the startup log can help diagnose startup issues
📝 Exercises
-
Basic Exercise (Difficulty: ⭐): Create a Spring Boot project, customize
banner.txt, change the service port to 9090, and after starting the project, verify that the/api/helloendpoint is accessible. -
Advanced Exercise (Difficulty ⭐⭐): Replace
SpringApplicationBuilderwithSpringApplication.run(), disable the banner, set the log level to DEBUG, and customize a/api/app-infoendpoint to return the application name and Java version. -
Challenge (Difficulty: ⭐⭐⭐): Implement
StartupListenerandApplicationListener<ApplicationStartedEvent>, record the application startup time, and print it to the log. Reflect on the design intent behind Spring Boot's event mechanism.



