Capítulo 01: Ecossistema Spring Boot 3, Starter Dependencies e Application Context
Especialização em Backend com Java & Spring Boot • Spring Boot 3 & Java 21 LTS • Spring Data JPA, Security, Microsserviços e Cloud
🗺️ Mapa Conceitual do Tópico
flowchart TD
A["Classpath do Projeto (Starters)"] --> B["@SpringBootApplication"]
B --> C["Auto-Configuration (@ConditionalOnClass)"]
C --> D["ApplicationContext / IoC Container"]
D --> E["Beans Gerenciados (@Service, @Repository, @Controller)"]
E --> F["Servidor Embutido (Tomcat) na Porta 8080"]
subgraph ARQ["Arquitetura do Capítulo"]
G["Spring Framework: IoC + DI"]
H["Spring Boot: Convenção sobre Configuração"]
I["application.yml + Profiles + @ConfigurationProperties"]
end
D --> ARQ
style A fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px
style B fill:#fff3e0,stroke:#ff9800,stroke-width:2px
style C fill:#ede7f6,stroke:#7e57c2,stroke-width:2px
style D fill:#e8f5e9,stroke:#4caf50,stroke-width:2px
style E fill:#fce4ec,stroke:#e91e63,stroke-width:2px
style F fill:#f3e5f5,stroke:#9c27b0,stroke-width:2px
🏛️ 1. Fundamentos Técnicos: Spring Framework, Spring Boot e o IoC Container
O Spring Framework resolve um problema antigo do Java corporativo: acoplamento manual entre objetos (new MeuService(new MeuRepository()) espalhado pelo código). Ele introduz o IoC Container (Inversion of Control), materializado na interface ApplicationContext, que passa a ser responsável por instanciar, configurar e injetar as dependências dos Beans da aplicação. Em vez de a classe controlar seu próprio ciclo de vida, o container o controla — daí “inversão”.
O Spring Boot 3 não substitui o Spring Framework: ele o encapsula com convenção sobre configuração. Três mecanismos fazem isso funcionar:
- Starter Dependencies (
spring-boot-starter-web,spring-boot-starter-data-jpa) são POMs “guarda-chuva” que trazem, de forma testada e compatível entre si, todas as bibliotecas transitivas necessárias para um recurso (ex.: ostarter-webtraz Tomcat embutido, Jackson e Spring MVC). - Auto-Configuration: ao subir o contexto, o Spring Boot varre classes anotadas com
@AutoConfiguratione decide quais Beans registrar usando anotações condicionais —@ConditionalOnClass(só ativa se a biblioteca estiver no classpath),@ConditionalOnMissingBean(só ativa se o desenvolvedor não tiver declarado seu próprio Bean, permitindo sobrescrever o padrão) e@ConditionalOnProperty(ativa/desativa viaapplication.yml). @SpringBootApplicationé uma meta-anotação que combina@Configuration(a classe pode declarar@Bean),@EnableAutoConfiguration(liga o mecanismo acima) e@ComponentScan(varre o pacote atual e subpacotes em busca de@Component,@Service,@Repository,@Controller) — por isso a classe principal deve ficar na raiz do pacote base do projeto.
Configuração externalizada é feita via application.yml/application.properties, mas expor essas propriedades como String soltas espalha “magic strings” pelo código. O padrão correto é o @ConfigurationProperties, hoje idiomático como Java Record (imutável, validável com Bean Validation, sem boilerplate de getters):
@ConfigurationProperties(prefix = "app.security")
public record SecurityProperties(
String jwtSecret,
int expirationMinutes,
boolean enableAudit
) {}
Isso exige @ConfigurationPropertiesScan (ou @EnableConfigurationProperties) habilitado na aplicação para que o record vire um Bean injetável.
Por fim, o próprio ApplicationContext pode ser injetado para introspecção — útil em diagnósticos, métricas customizadas ou frameworks internos que precisam listar Beans dinamicamente via getBeanDefinitionNames() ou getBeansOfType(Classe.class).
💻 2. Código de Demonstração Corporativo
// Application.java — ponto de entrada e Auto-Configuration condicional
package com.empresa.api;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
@ConfigurationPropertiesScan
public class Application implements CommandLineRunner {
private final ApplicationContext context;
public Application(ApplicationContext context) {
this.context = context;
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
public void run(String... args) {
long totalServices = java.util.Arrays.stream(context.getBeanDefinitionNames())
.filter(name -> context.getType(name) != null
&& context.getType(name).isAnnotationPresent(org.springframework.stereotype.Service.class))
.count();
System.out.printf("Spring Boot 3 inicializado. %d beans de servico registrados.%n", totalServices);
}
}
// MetricsAutoConfiguration.java — Bean condicional, ativado só se a propriedade permitir
package com.empresa.api.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MetricsAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "app.metrics.enabled", havingValue = "true")
@ConditionalOnMissingBean
public MetricsService metricsService() {
return new MetricsService();
}
public static class MetricsService {
public void registrar(String evento) {
System.out.println("Metrica registrada: " + evento);
}
}
}
O @ConditionalOnMissingBean é o que permite a um desenvolvedor sobrescrever qualquer auto-configuração padrão do Spring Boot simplesmente declarando seu próprio @Bean do mesmo tipo — é a base de como o próprio framework se mantém extensível sem quebrar compatibilidade.