Sua Primeira Aplicação Spring Boot
Uma única anotação @SpringBootApplication é tudo o que é necessário para iniciar toda a aplicação—a mágica do Spring Boot está na combinação engenhosa de três anotações.
1. O Que Você Vai Aprender
- Princípios de Decomposição e Combinação da Anotação
@SpringBootApplication - Métodos
main()da Classe Principal de Inicialização e Fluxo de Execução doSpringApplication.run() - Formatos de Arquivo de Configuração
application.propertiesvsapplication.yml - Personalizando o Banner do Spring Boot e Interpretando Logs de Inicialização
- Executar a primeira interface "Hello OrderFlow"
2. Uma História Real Sobre um Novo Projeto
(1) Ponto de Dor: Leva meio dia para configurar um projeto
Alice lembrou de sua experiência usando o Spring MVC tradicional quando começou: criar um projeto exigia configurar web.xml, applicationContext.xml e spring-mvc.xml, além de instalar o Tomcat e configurar a fonte de dados JNDI. Apenas fazer o projeto funcionar levava meio dia, sem falar na depuração de ordem de inicialização e problemas de carregamento de beans.
(2) A Solução do Spring Boot
O Spring Boot requer apenas uma anotação e um método main:
@SpringBootApplication
public class OrderFlowApplication {
public static void main(String[] args) {
SpringApplication.run(OrderFlowApplication.class, args);
}
}
(3) Resultado
Alice usou o Spring Boot para criar o projeto OrderFlow. Levou apenas 5 minutos desde o início até a primeira resposta da API—sem XML, sem container externo, e os logs de inicialização eram claros e fáceis de ler.
3. Decompondo a Anotação @SpringBootApplication
(1) Uma combinação de três anotações
@SpringBootApplication é uma anotação composta equivalente a usar as três anotações seguintes simultaneamente:
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"]
| Anotação | Função | Notação Tradicional Equivalente |
|---|---|---|
@SpringBootConfiguration |
Marca a classe atual como uma classe de configuração | @Configuration |
@EnableAutoConfiguration |
Ativa Auto-Configuração | @EnableAutoConfiguration |
@ComponentScan |
Scanning de Componentes | <context:component-scan> |
(2) Regras de scanning do @ComponentScan
@ComponentScan Por padrão, o scanning cobre o pacote que contém a classe principal de inicialização e todos os seus subpacotes.
com.orderflow ← O pacote que contém a classe principal de inicialização
├── OrderFlowApplication.java ← @SpringBootApplication
├── controller/ ← Escaneado por @ComponentScan
│ └── OrderController.java
├── service/ ← Escaneado por @ComponentScan
│ └── OrderService.java
└── repository/ ← Escaneado por @ComponentScan
└── OrderRepository.java
com.other ← ⚠️ Não incluído no scanning!
4. Processo de Inicialização do SpringApplication.run()
(1) Sequência de Inicialização
O processo de execução do SpringApplication.run() é um pipeline cuidadosamente projetado:
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) Determinando o Tipo de Aplicação Web
O Spring Boot Detecta Automaticamente o Tipo de Aplicação:
| Condição | Tipo | Container Usado |
|---|---|---|
classpath contém spring-webmvc |
SERVLET | Tomcat / Jetty / Undertow |
classpath contém spring-webflux mas não spring-webmvc |
REACTIVE | Netty |
| Nenhum | NONE | Sem containers embarcados |
(1) ▶ Exemplo: Personalizando a Inicialização do SpringApplication
@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);
}
}
Saída:
// Execução bem-sucedida
5. Formato do Arquivo de Configuração
(1) Properties vs. YAML
O Spring Boot suporta dois formatos de arquivo de configuração que são funcionalmente equivalentes, mas diferem na sintaxe.
(1) ▶ Exemplo: Como escrever 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
Saída:
// Execução bem-sucedida
(2) ▶ Exemplo: Como escrever 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
Saída:
A configuração entrou em vigor.
| Dimensão | Properties | YAML |
|---|---|---|
| Estrutura Hierárquica | Separada por . |
Indicação Indica Hierarquia |
| Legibilidade | Pares chave-valor simples, planos | Hierarquia clara, adequada para aninhamento |
| Suporte a Listas | list[0]=a |
- a Mais Intuitivo |
| Prefixo Repetido | Deve ser repetido | Prefixo compartilhado no mesmo nível |
| Desempenho de Parsing | Mais rápido | Um pouco mais lento (requer parsing de hierarquia) |
| Prioridade | Igual | Igual (properties tem precedência quando ambos existem) |
(2) Referência Rápida de Opções de Configuração Comuns
| Opção de Configuração | Valor Padrão | Descrição |
|---|---|---|
server.port |
8080 | Porta de Escuta da Aplicação |
spring.application.name |
— | Nome da Aplicação |
server.servlet.context-path |
/ | Caminho de Contexto |
spring.main.banner-mode |
console | Modo de Exibição do Banner |
spring.jpa.show-sql |
false | Imprimir SQL |
logging.level.root |
INFO | Nível de Log Global |
6. Personalizando o Banner e os Logs de Inicialização
(1) Banner Personalizado
Coloque um banner personalizado em src/main/resources/banner.txt para que seja exibido automaticamente quando o Spring Boot iniciar.
(1) ▶ Exemplo: Banner Personalizado do OrderFlow
____ _ ____ __
/ ___| _ __ __ _| |_ ___ / ___|| | ___ _ __
| | | '_ \ / _` | __/ _ \ \___ \| |/ _ \| '_ \
| |___ | | | | (_| | || __/ ___) | | (_) | | | |
\____||_| |_|\__,_|\__\___| |____/|_|\___/|_| |_|
:: OrderFlow Service :: v${application.version:1.0.0}
:: Spring Boot ${spring-boot.version} ::
Saída:
Execução bem-sucedida
(2) Interpretando o Log de Inicialização
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | | || (_| | / / / /
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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
| Palavras-chave do Log | Significado |
|---|---|
Starting OrderFlowApplication |
Aplicação iniciando |
Tomcat initialized with port |
Iniciando Tomcat Embarcado |
Bootstrapping Spring Data JPA |
Configurando Automaticamente o Repositório JPA |
Started in X seconds |
Inicialização concluída, demorou |
7. Execute Sua Primeira Interface "Hello OrderFlow"
(1) ▶ Exemplo: Controller Hello OrderFlow
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()
);
}
}
Saída:
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) ▶ Exemplo: Usando @Value para injeção de configuração
@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")
);
}
}
Saída:
// Execução bem-sucedida
8. Exemplo Abrangente: Configuração Completa de Inicialização do OrderFlow
// 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"}
❓ Perguntas Frequentes
properties e YAML podem coexistir?properties tem precedência. Recomenda-se usar apenas um para evitar confusão. Recomendamos YAML, pois oferece uma hierarquia mais clara.spring.main.banner-mode=off no arquivo de configuração, ou app.setBannerMode(Banner.Mode.OFF) no código.server.port=8081, ou localize e encerre o processo usando a porta: lsof -i :8080 (Linux/Mac) ou netstat -ano | findstr 8080 (Windows).ddl-auto=validate causa conexões lentas com bancos de dados remotos; 3) Auto-configurações desnecessárias não foram excluídas. Use o modo --debug para ver detalhes.<mainClass> no plugin Maven; execute diretamente a classe que contém o método main na IDE; o Spring Boot Maven Plugin detectará automaticamente durante o empacotamento.📖 Resumo
@SpringBootApplication=@Configuration+@EnableAutoConfiguration+@ComponentScan- A classe principal de inicialização deve ser colocada no pacote raiz para garantir que o scanning de componentes cubra todos os subpacotes
SpringApplication.run()Percorre o processo completo de configuração do ambiente → criação do contexto → refresh → instanciação de beans- YAML e Properties são funcionalmente equivalentes; YAML tem hierarquia mais clara, enquanto Properties são analisados mais rapidamente
- Personalize o banner usando
banner.txt; o log de inicialização pode ajudar a diagnosticar problemas de inicialização
📝 Exercícios
-
Exercício Básico (Dificuldade: ⭐): Crie um projeto Spring Boot, personalize o
banner.txt, altere a porta do serviço para 9090, e após iniciar o projeto, verifique se o endpoint/api/helloestá acessível. -
Exercício Avançado (Dificuldade ⭐⭐): Substitua
SpringApplication.run()porSpringApplicationBuilder, desative o banner, defina o nível de log para DEBUG, e personalize um endpoint/api/app-infopara retornar o nome da aplicação e a versão do Java. -
Desafio (Dificuldade: ⭐⭐⭐): Implemente
StartupListenereApplicationListener<ApplicationStartedEvent>, registre o tempo de inicialização da aplicação e imprima-o no log. Reflita sobre a intenção de design por trás do mecanismo de eventos do Spring Boot.



