Vamos a arrancar por el principio. ¿Qué son Spring y Spring Boot?

" Spring es el framework que ordenó el quilombo del Java enterprise. Spring Boot es el que después vino y dijo: buenísimo todo, pero capaz no hacía falta sufrir tres días para levantar una app que diga hola. "

Si laburás con Java, tarde o temprano te cruzás con Spring. A veces aparece como salvación, a veces como monstruo con anotaciones, y a veces como ese sistema viejo de la empresa que nadie quiere tocar porque “funciona” y porque el último que lo reinició se jubiló cuando Mirtha Legrand cumplió los 60. Pero abajo de toda esa mitología hay una idea bastante concreta: Spring ayuda a construir aplicaciones Java más ordenadas, desacopladas y mantenibles.

Spring Boot llegó después para simplificar todavía más la experiencia: autoconfiguración, starters, servidor embebido, configuración externa y una forma mucho más directa de crear una aplicación ejecutable. Spring te da los ladrillos, la leña y la carne; Spring Boot te da el medio tanque ya prendido y con las brasas a punto. Pasás de 'ponete a levantar la pared de la churrasquera' a 'tirá los chorizos que esto ya tiene fuego'.

Comentario creado por la IA, no es mío

Spring no apareció para hacer Java más mágico. Apareció para hacer Java enterprise menos traumático. Que después algunos proyectos hayan usado esa libertad para crear 47 capas para devolver un string ya es otro capítulo de la novela.

Este sí es mío

Cuando armó la analogía de la churrasquera encajó: (Nivel de uruguayez: 100%). Le doy la derecha en que usó el asado para la analogía, pero está claro que la IA tiene recorrido para reemplazar a un Uruguayo escribiendo.

MHO (Mi humilde opinión... que en realidad es de ChatGPT)

Spring y Spring Boot son tecnologías que conviene entender con calma, no desde el fanatismo ni desde el trauma. Spring puede parecer enorme porque efectivamente es enorme, pero su corazón es bastante noble: separar responsabilidades, conectar piezas, facilitar tests y evitar que cada clase salga a buscar dependencias como quien busca monedas abajo del sillón. Boot, por su lado, hizo algo muy necesario: bajar la barrera de entrada. Porque una tecnología puede ser poderosísima, pero si para mostrar “Hola mundo” necesitás invocar al comité de arquitectura, algo raro está pasando.

Antes de Spring: Java enterprise era más áspero

Para entender por qué Spring pegó tan fuerte, hay que mirar un poco el paisaje anterior. A fines de los 90 y principios de los 2000, el desarrollo empresarial en Java estaba muy asociado a J2EE, servidores de aplicaciones pesados, despliegues en WAR o EAR, mucho XML, JNDI, EJB y una cantidad de configuración que por momentos parecía más una ceremonia administrativa que programación.

No es que Java EE no tuviera potencia. La tenía. El tema era la fricción. Para resolver problemas simples muchas veces terminabas montando una infraestructura enorme, con objetos difíciles de probar y una dependencia fuerte del servidor de aplicaciones. Era como llevar una retroexcavadora para plantar una albahaca: técnicamente se puede, pero capaz te estás complicando un poquito.

Mucho servidor

La app solía depender fuertemente de un contenedor externo grande, con despliegues más pesados y más ceremonia.

Mucho XML

Había bastante configuración explícita. Flexible, sí, pero a veces más larga que explicación de bug en retrospectiva.

Mucho acoplamiento

Probar partes aisladas podía volverse difícil si todo estaba pegado a infraestructura pesada.

Spring nació como reacción a esa complejidad accidental. Rod Johnson empezó a trabajar en el código original en 2001 y lo publicó junto con su libro de 2002. La idea no era hacer “otro framework porque sí”, sino ofrecer una alternativa más liviana, más testeable y más flexible para construir aplicaciones empresariales sin cargar con tanto ritual innecesario.

Entonces, ¿qué es exactamente Spring?

Spring Framework es la base del ecosistema. Su pieza central es el IoC Container, también conocido como contenedor de inversión de control. Dicho sin corbata: en vez de que tus clases creen y administren todo lo que necesitan, Spring se encarga de crear objetos, conectarlos, configurarlos y entregarlos donde corresponda.

Eso permite escribir código más desacoplado. Una clase no tiene que saber cómo se construye todo el universo que la rodea; simplemente declara lo que necesita. Spring arma el cableado. Y cuando querés testear, podés reemplazar dependencias reales por mocks o implementaciones alternativas sin demoler media aplicación.

Resumen brutalmente honesto

Spring sirve para construir aplicaciones Java serias sin que cada clase viva pegada con cinta a todas sus dependencias. No es solamente inyección de dependencias, aunque esa sea una de sus ideas más famosas. Es contenedor, configuración, transacciones, acceso a datos, web, seguridad, integración y un ecosistema gigante alrededor.

Las ideas fuertes de Spring

Inyección de dependencias

Las clases reciben lo que necesitan en vez de fabricarlo internamente como si estuvieran en una feria de objetos.

Contenedor de beans

Spring crea y administra los objetos principales de la aplicación, su ciclo de vida y sus relaciones.

AOP y preocupaciones transversales

Logs, transacciones, seguridad y otras tareas pueden separarse del código de negocio.

Acceso a datos y transacciones

Facilita trabajar con JDBC, JPA, repositorios y manejo transaccional sin escribir siempre la misma novela.

¿Y Spring Boot qué agrega?

Spring Boot no reemplaza a Spring. Lo simplifica. Apareció para que arrancar una aplicación Spring no fuera una procesión de configuración inicial. Boot mira qué dependencias tenés, aplica convenciones razonables, autoconfigura lo común y te permite levantar una app ejecutable sin depender necesariamente de un servidor externo.

Si Spring te da una cocina profesional, Boot te deja varias cosas listas para que no tengas que empezar fabricando la hornalla. Agregás un starter web, corrés el main, y tenés una app escuchando en el puerto 8080. No será Netflix, pero para arrancar ya es bastante más digno que pelearte con XML hasta las dos de la mañana.

Diferencia conceptual entre Spring Framework y Spring Boot
Concepto Spring Framework Spring Boot
Rol principal Base del ecosistema Capa de arranque y simplificación
Configuración Muy flexible, pero puede requerir más setup Autoconfiguración con convenciones razonables
Dependencias Se eligen módulo por módulo Usa starters para agrupar dependencias comunes
Ejecución Tradicionalmente más asociado a contenedores externos Muy cómodo con java -jar y servidor embebido

Las tres bombas de productividad de Spring Boot

1. Autoconfiguración

Boot detecta qué tenés en el classpath y configura automáticamente una base razonable. No reemplaza entender qué pasa, pero te evita escribir configuración repetida como si estuvieras pagando penitencia.

2. Starters

En vez de buscar veinte dependencias sueltas, agregás algo como spring-boot-starter-web y recibís un combo coherente para construir una app web con Spring MVC.

3. Aplicaciones ejecutables

Empaquetás la app y la corrés con java -jar. El servidor web puede ir embebido, así que no necesitás instalar un Tomcat aparte solo para probar tu primer endpoint.

Historia corta de Spring: del barro J2EE al presente

Spring no nació como moda. Nació porque había dolor real. Mucha gente construyendo aplicaciones Java empresariales sentía que la infraestructura se comía al producto. Spring propuso un modelo más liviano, más testeable y más orientado a objetos simples. Desde su primera versión ya tenía varias piezas que todavía reconocemos: IoC, transacciones, abstracciones JDBC, soporte DAO, AOP y una pila web.

1

Spring Framework 1.0 — 24 de marzo de 2004

Primera versión final. El ADN ya estaba ahí: contenedor IoC, transacciones, JDBC, DAO, AOP y soporte web.

2

Spring Framework 2.0 — 3 de octubre de 2006

Mejoras grandes en configuración y AOP. Menos pelea cuerpo a cuerpo con el framework, más foco en resolver el problema real.

3

Spring Framework 3.0 — 16 de diciembre de 2009

Se consolida el estilo moderno basado en anotaciones, alineado con Java EE 6 y JPA 2.0.

4

Spring Framework 4.0 — 12 de diciembre de 2013

Java 8, WebSocket, REST y una mirada más moderna hacia microservicios.

5

Spring Framework 5.0 — 28 de septiembre de 2017

WebFlux, Reactor, Kotlin, JUnit 5 y programación reactiva. Spring no se quedó mirando desde la tribuna.

6

Spring Framework 6.0 — 16 de noviembre de 2022

Java 17 como baseline y salto importante al namespace jakarta.*.

7

Spring Framework 7.0 — 13 de noviembre de 2025

Nueva generación, base para Spring Boot 4, con foco en Java 25, Jakarta EE 11, JSpecify y Jackson 3.

Comentario creado por la IA, no es mío

Spring no es “el framework viejo que sigue por costumbre”. Es viejo como ese senior que vio caer tres arquitecturas, sobrevivió a cinco migraciones y todavía te arregla un incidente con dos logs y una cara de cansancio existencial.

Historia corta de Spring Boot: cuando Spring se puso cómodo

Spring Boot llegó en 2014 y cambió la experiencia diaria. Ya no se trataba solo de tener un framework potente, sino de poder crear una app funcional rápido, con menos configuración inicial y un modelo de despliegue más simple. En vez de armar todo a mano, Boot te ofrece convenciones razonables y una estructura lista para empezar.

Spring Boot 1.0 — 1 de abril de 2014

Autoconfiguración, starters y aplicaciones ejecutables como propuesta central. El “corré el main y vemos” empezó a tomar forma.

Spring Boot 2.0 — 1 de marzo de 2018

Java 8 como baseline, WebFlux, Netty embebido, HTTP/2, Kotlin y Actuator rediseñado.

Spring Boot 3.0 — 24 de noviembre de 2022

Java 17, Jakarta EE, observabilidad moderna y soporte para imágenes nativas con GraalVM.

Spring Boot 4.0 — 20 de noviembre de 2025

Nueva generación sobre Spring Framework 7.0, modularización más fina, JSpecify, API versioning y HTTP service clients.

Detalle para no mezclar generaciones

Spring Boot 3.x se mueve sobre Spring Framework 6.x. Spring Boot 4.x se mueve sobre Spring Framework 7.x. Si estás migrando un proyecto real, no es “subir numerito y rezar”: hay cambios de dependencias, compatibilidad, Java baseline, Jakarta, APIs y bueno, después de todo eso, rezar.

¿Qué demonios es un release train?

En el ecosistema Spring vas a escuchar mucho la expresión release train. Suena a nombre de reunión con mucho PowerPoint, pero tiene sentido. Un release train es una forma de coordinar versiones de varios proyectos relacionados para que sean compatibles entre sí y se puedan consumir como un bloque coherente.

Por ejemplo, Spring Data tiene muchos módulos: JPA, MongoDB, Redis, JDBC, Elasticsearch y más. Cada módulo podría evolucionar a su ritmo, pero para el usuario final sería un caos andar adivinando qué versión combina con cuál. Entonces se publica un conjunto coordinado, normalmente consumido mediante un BOM (Bill of Materials), que define versiones compatibles.

Versión rioplatense

Un release train es Spring diciendo: “usá estas versiones juntas, que ya nos peleamos nosotros para que no te pelees vos”. Es menos heroico que resolver dependencias a mano, pero bastante más sano para tu presión arterial.

Hello World real con Spring Boot

Vamos con una aplicación mínima pero funcional. La idea es levantar una web en http://localhost:8080/ que muestre un mensaje simple. No vamos a meter base de datos, seguridad, Docker, Kafka ni una arquitectura hexagonal para imprimir un saludo. Tranquilos. Todavía somos personas.

Este ejemplo usa Spring Boot 3.5.6, que requiere al menos Java 17 (aunque se recomienda Java 21, el LTS actual). Para una aplicación web clásica con Spring MVC, usamos el starter spring-boot-starter-web. Vamos a separar la clase principal de la aplicación del controlador, como se hace en proyectos reales.

Estructura mínima del proyecto

hola-spring/
├── pom.xml
└── src/
    └── main/
        ├── java/
        │   └── com/
        │       └── ejemplo/
        │           └── holaspring/
        │               ├── HolaSpringApplication.java
        │               └── HolaController.java
        └── resources/
            └── application.properties

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         https://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.5.6</version>
        <relativePath/>
    </parent>

    <groupId>com.ejemplo</groupId>
    <artifactId>hola-spring</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>hola-spring</name>
    <description>Hello World mínimo con Spring Boot</description>

    <properties>
        <java.version>21</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

HolaSpringApplication.java

La clase principal solo arranca Spring Boot. Nada más, nada menos.

package com.ejemplo.holaspring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HolaSpringApplication {

    public static void main(String[] args) {
        SpringApplication.run(HolaSpringApplication.class, args);
    }
}

HolaController.java

El controlador define qué responder a cada URL. @RestController le indica a Spring que esta clase atiende requests HTTP y devuelve el valor de cada método directamente como respuesta. @GetMapping("/") mapea el método al GET /.

package com.ejemplo.holaspring;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HolaController {

    @GetMapping("/")
    public String home() {
        return "Hola desde Spring Boot. Si ves esto en el puerto 8080, la criatura arrancó bien.";
    }
}

application.properties

spring.application.name=hola-spring
server.port=8080

Con eso alcanza. Corrés la aplicación, entrás a http://localhost:8080/ y deberías ver el mensaje. No es la app del siglo, claro. Pero para primer contacto está perfecto: compila, levanta, escucha en 8080 y responde. Ya con eso le ganaste a unas cuantas tardes de XML del pasado.

application.properties vs application.yaml

Spring Boot permite externalizar configuración. Eso significa que podés cambiar comportamiento sin tocar código: puerto, nombre de la aplicación, perfiles, logs, base de datos, seguridad, integraciones y bastante más. Los dos formatos más comunes son application.properties y application.yaml.

application.properties

spring.application.name=hola-spring
server.port=8080
logging.level.root=INFO

application.yaml

spring:
  application:
    name: hola-spring

server:
  port: 8080

logging:
  level:
    root: INFO

No mezcles por deporte

Si tenés application.properties y application.yaml en la misma ubicación, puede haber reglas de prioridad. Mi recomendación terrenal: elegí uno y mantené consistencia en el proyecto.

Cómo correr una aplicación Spring Boot

Una de las grandes comodidades de Boot es que tenés varias formas simples de ejecutar la app. Para desarrollo local, lo más común es correr la clase main desde el IDE o usar Maven. Para despliegue, suele aparecer el JAR ejecutable.

Desde el IDE

Ejecutás la clase principal y Boot levanta el contexto junto con el servidor web.

Con Maven

./mvnw spring-boot:run

Como JAR

./mvnw clean package
java -jar target/hola-spring-0.0.1-SNAPSHOT.jar

Tomcat, Jetty, JAR o WAR: las formas de desplegar

En una aplicación web clásica con Spring Boot, lo normal hoy es usar un servidor embebido. Eso significa que tu aplicación trae el servidor adentro. En Spring Boot 4, para aplicaciones servlet, el default habitual es Tomcat, y también podés usar Jetty si preferís cambiar el contenedor.

Opciones habituales de ejecución y despliegue
Opción Cuándo usarla Comentario terrenal
JAR con Tomcat embebido La opción más común para APIs y servicios Spring Boot MVC Simple, directo y muy usado en producción
JAR con Jetty embebido Cuando querés usar Jetty en vez de Tomcat Cambiás dependencias y Boot se adapta
WAR en contenedor externo Entornos heredados o corporativos donde ya existe un servidor Sigue siendo posible, aunque hoy no suele ser la primera opción
WAR ejecutable Cuando querés flexibilidad entre contenedor externo y ejecución directa Útil, pero conviene saber bien por qué lo necesitás

¿Y si quiero WAR?

Podés cambiar el packaging en Maven:

<packaging>war</packaging>

Y normalmente adaptar tu clase principal para extender SpringBootServletInitializer. Esto permite desplegar la app en un contenedor servlet externo. Es común en ambientes legacy, donde el despliegue ya está armado alrededor de Tomcat, WebLogic, WebSphere u otro bicho corporativo que nadie quiere tocar porque “si anda, no lo mires fuerte”.

Antes de entusiasmarte de más: cuatro warnings para no comprar humo

1. Spring Boot no elimina la necesidad de entender Spring

Te ayuda a arrancar más rápido, pero cuando algo falla necesitás saber qué está autoconfigurando, qué beans existen y cómo se arma el contexto.

2. La autoconfiguración no es magia negra

Es código condicional basado en dependencias, propiedades y beans existentes. Parece magia hasta que abrís el reporte de condiciones y ves que el mago también tenía un if.

3. Migrar versiones mayores requiere respeto

Pasar de Boot 2 a 3 o de 3 a 4 puede implicar cambios fuertes: Java baseline, Jakarta, dependencias, APIs y compatibilidad con proyectos del ecosistema.

4. No metas arquitectura de cohete para un carrito de choripanes

Spring te deja hacer sistemas enormes, pero para apps chicas conviene mantener la estructura simple. La sobredosis de capas también enferma.

Qué te tenés que llevar de esto

  • Spring nació para bajar la complejidad accidental del Java enterprise
  • Spring Boot nació para bajar la complejidad de usar Spring y permitir arrancar más rápido
  • La autoconfiguración ayuda mucho, pero no reemplaza entender cómo se arma la aplicación
  • Los starters agrupan dependencias coherentes para casos de uso comunes
  • El JAR ejecutable con servidor embebido cambió muchísimo la experiencia de correr y desplegar apps
  • Los release trains ayudan a mantener compatibilidad entre proyectos del ecosistema

Comentario creado por la IA, no es mío

En otras palabras: Spring no es solo una tecnología. Es el momento en que Java enterprise dejó de decirte “primero sufrí un poco” como requisito de ingreso. Y Spring Boot es el amigo que te abre la puerta, te muestra dónde está la documentación y te dice: “dale, corré el main, después vemos”.

Fuentes y data extra

Toda la información de este post se roba inspira de acá:

Para historia, versiones, configuración, servidores embebidos, despliegue tradicional y compatibilidad entre proyectos, las fuentes principales son documentación y anuncios oficiales del ecosistema Spring.

Nota de compatibilidad

Las versiones modernas cambian rápido. Antes de usar este ejemplo en un proyecto real, revisá la línea estable actual y la compatibilidad con Java, Maven, Gradle, Spring Framework y Spring Cloud.