A classe SpringApplication é o ponto central para a inicialização de aplicações Spring Boot. Geralmente executada a partir de um método main, ela coordena a criação do contexto, a configuração do ambiente e a execução de listeners.
O Processo de Instalação no Construtor
Ao instanciar uma SpringApplication, o framework realiza diagnósticos preliminares para definir o comportamento da aplicação. O código abaixo ilustra a lógica interna de inicialização:
public SpringApplication(ResourceLoader carregadorRecurso, Class<?>... fontesBase) {
this.resourceLoader = carregadorRecurso;
Assert.notNull(fontesBase, "As fontes principais não podem ser nulas.");
this.primarySources = new LinkedHashSet<>(Arrays.asList(fontesBase));
// Identifica se a aplicação é Web (Servlet ou Reactive) ou Standard
this.webApplicationType = identificarTipoAplicacao();
// Carrega inicializadores definidos em META-INF/spring.factories
setInitializers((Collection) localizarInstancias(ApplicationContextInitializer.class));
// Carrega ouvintes (listeners) de eventos do ciclo de vida
setListeners((Collection) localizarInstancias(ApplicationListener.class));
// Identifica a classe que contém o método main
this.mainApplicationClass = localizarClassePrincipal();
}
Detecção do Tipo de Ambiente Web
O Spring Boot diferencia o ambiente de execução baseando-se na presença de classes específicas no classpath. Existem três categorias: NONE (não-web), SERVLET (Spring MVC tradicional) e REACTIVE (Spring WebFlux).
private WebApplicationType identificarTipoAplicacao() {
boolean possuiWebflux = ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null);
boolean possuiMvc = ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null);
if (possuiWebflux && !possuiMvc) {
return WebApplicationType.REACTIVE;
}
String[] classesServlet = { "javax.servlet.Servlet", "org.springframework.web.context.ConfigurableWebApplicationContext" };
for (String nomeClasse : classesServlet) {
if (!ClassUtils.isPresent(nomeClasse, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
O Fluxo do Método run()
O método run é onde a execução propriamente dita acontece. Ele gerencia desde o cronômetro de inicialização até a notificação final de que o serviço está pronto.
public ConfigurableApplicationContext run(String... argumentos) {
StopWatch cronometro = new StopWatch();
cronometro.start();
ConfigurableApplicationContext contexto = null;
Collection<SpringBootExceptionReporter> relatoresErro = new ArrayList<>();
// Configura modo headless para ambientes sem interface gráfica
ajustarPropriedadeHeadless();
// Notifica listeners que a inicialização começou
SpringApplicationRunListeners ouvintes = obterOuvintesExecucao(argumentos);
ouvintes.starting();
try {
ApplicationArguments argsApp = new DefaultApplicationArguments(argumentos);
// Prepara o ambiente (propriedades, perfis, etc.)
ConfigurableEnvironment ambiente = prepararAmbiente(ouvintes, argsApp);
configurarIgnorarBeanInfo(ambiente);
// Exibe o Banner no console
Banner bannerExibido = imprimirBanner(ambiente);
// Instancia o ApplicationContext adequado ao tipo de webApplicationType
contexto = criarContextoAplicacao();
// Prepara os analisadores de falhas na inicialização
relatoresErro = localizarInstancias(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, contexto);
// Configura o contexto antes do refresh (vincula ambiente, injeta beans iniciais)
prepararContexto(contexto, ambiente, ouvintes, argsApp, bannerExibido);
// Processo principal de criação de beans e refresh do IoC
atualizarContexto(contexto);
posAtualizacao(contexto, argsApp);
cronometro.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getLog(), cronometro);
}
// Informa que o contexto foi totalmente carregado
ouvintes.started(contexto);
// Executa componentes do tipo CommandLineRunner ou ApplicationRunner
executarRunners(contexto, argsApp);
} catch (Throwable ex) {
tratarFalha(contexto, ex, relatoresErro, ouvintes);
throw new IllegalStateException(ex);
}
try {
ouvintes.running(contexto);
} catch (Throwable ex) {
tratarFalha(contexto, ex, relatoresErro, null);
throw new IllegalStateException(ex);
}
return contexto;
}
Diferenças de Contexto: Spring MVC vs. Spring Boot
Uma distinção fundamental entre o modelo tradicional do Spring MVC e o Spring Boot reside na hierarquia de contextos.
Arquitetura Tradicional (Spring MVC)
No Spring MVC legado, é comum encontrar dois contextos distintos:
- Root WebApplicationContext: Geralmente carregado via
ContextLoaderListener, contém beans de serviço e repositórios. - Servlet WebApplicationContext: Vinculado a uma
DispatcherServletespecífica, contenod beans de infraestrutura web (Controllers, ViewResolvers).
O DispatcherServlet não é gerenciado pelo Spring nativamente; ele busca o contexto raiz no ServletContext para estabelecer a relação pai-filho.
Arquitetura Spring Boot
No Spring Boot, por padrão, utiliza-se um único contexto unificado (AnnotationConfigServletWebServerApplicationContext para aplicações Servlet).
Diferente do modelo legado, o DispatcherServlet no Spring Boot é registrado como um Bean dentro do próprio contexto do Spring. Quando o servidor web embutido (como Tomcat) inicia, o Spring Boot injeta o contexto único diretamente no servlet. Isso simplifica a gestão de dependências, permitindo que o DispatcherServlet utilize injeção de dependência padrão para acessar o ApplicationContext.
// Exemplo simplificado da criação do servidor web embutido no contexto
protected void onRefresh() {
super.onRefresh();
try {
// Localiza a fábrica (Tomcat, Jetty ou Undertow) e sobe o servidor
ServletWebServerFactory fabrica = getWebServerFactory();
this.webServer = fabrica.getWebServer(getSelfInitializer());
} catch (Throwable ex) {
throw new ApplicationContextException("Falha ao iniciar servidor web", ex);
}
}
Esta abodragem de contexto único facilita testes de integração e reduz a complexidade de configuração, eliminando a necessidade de múltiplos arquivos XML ou classes de configuração redundantes para separar Beans de infraestrutura de Beans de negócio.