Micronaut
Durante más de dos décadas, los frameworks en el ecosistema Java han confiado fuertemente en la reflexión en tiempo de ejecución (runtime reflection), la carga dinámica de clases y la generación de proxies en memoria para implementar Inyección de Dependencias (DI) y Programación Orientada a Aspectos (AOP) siendo Spring el framework de referencia en el desarrollo de aplicaciones.
Esta arquitectura funcionó bien durante la era de los servidores de aplicaciones monolíticos que funcionaban de forma ininterrumpida. Sin embargo, en el paradigma actual de contenedores (Docker/Kubernetes), microservicios y Serverless, este modelo tradicional presenta dos problemas graves: tiempos de arranque elevados y un alto consumo de memoria RAM.
En 2018 Graeme Rocher, el principal desarrollador de Grails (un framework basado en Spring y Groovy), presentó en el Greach de Madrid un proyecto en el que había empezado a trabajar Youtube
En esta presentación Graeme mostró las bases de lo que sería Micronaut
¿Qué es Micronaut?
Micronaut es un framework JVM moderno y modular diseñado específicamente para la construcción de microservicios y aplicaciones cloud-native. Fue creado por el equipo detrás de Grails (Object Computing, Inc.) con una premisa fundamental: hacer en tiempo de compilación todo lo que tradicionalmente se hacía en tiempo de ejecución.
Características
- Compilación Ahead-Of-Time (AOT): Micronaut utiliza procesadores de anotaciones (JSR-269 en Java, KSP en Kotlin o AST Transformations en Groovy) para calcular el grafo de dependencias, validar anotaciones y generar los metadatos necesarios durante la fase de compilación del proyecto
- Cero reflexión en runtime: Al no depender de la reflexión para la inyección de dependencias, el tiempo de arranque de la aplicación es prácticamente independiente de la cantidad de beans o controladores que tenga el proyecto
- Consumo mínimo de memoria: La eliminación de caches de reflexión internas permite que la aplicación arranque consumiendo una fracción de la memoria RAM requerida por otros frameworks tradicionales.
Maven o Gradle
Micronaut es compatible con Maven y Gradle, simplemente al crear el proyecto decides cúal quieres usar.
![]() |
Personalmente, prefiero Gradle y es lo que usaremos en el libro, pero si quieres usar Maven simplemente debes
indicárselo al comando |
Java, Kotlin o Groovy
Micronaut, a diferencia de otros frameworks JVM como Quarkus por ejemplo, puede trabajar con Java, Kotlin o Groovy sin problemas.
![]() |
Yo soy un fan de Groovy, pero en los ejemplos del libro usaremos Java por ser el lenguaje más común en el ecosistema JVM. |
Versiones
Al tiempo de escribir este libro Micronaut se encuentra en su versión 5.0.x y es la que usaremos, aunque versiones anteriores son también perfectamente válidas.
Si bien Micronaut demuestra ser un framework muy vivo, con releases frecuentes, la transición entre ellas es muy cuidada y fácil.
En muchos casos basta con cambiar el número de versión y todo el proyecto sigue siendo válido. En mi experiencia personal la mayor dificultad se presentó al pasar de las versiones 2.x a 3.x, pero no he encontrado mayores problemas al pasar de 3.x a 4.x o recientemente de 4.x a 5.x, aunque siempre dependerá de las dependencias y características de tu propio proyecto
Singleton e Inject
A lo largo del libro iremos usando diferentes funcionalidades de Micronaut, casi todas implementadas por el framework mediante anotaciones, pero antes de irlas descubriendo nos pararemos un segundo a explicar las dos que más se usan a lo largo del libro.
Si has trabajado con Spring las anotaciones @Bean , @Service, @Prototype, etc. te sonarán familiares.
Con estas anotaciones indicamos al framework que estas clases son especiales y que están destinadas a ser inyectadas en otras clases, bien mediante métodos setXXX o, preferiblemente, en el constructor de las clases dependientes de ellas.
De forma similar Micronaut no solo proporciona las suyas propias, sino que utiliza las definidas en los JSR como por ejemplo @Singleton
Con esta anotación indicamos al framework que nuestra aplicación requiere de una sóla instancia de esta clase, la cual deberá ser proporcionada en aquellos puntos en las que se indique.
Un ejemplo sencillo:
1 @Singleton
2 public class TestService{
3
4 void sayHello(){
5 System.out.println("Hello");
6 }
7
8 }
9
10 @Singleton
11 public class UseCase1{
12
13 @Inject
14 TestService testService;
15
16 void doIt(){
17 testService.sayHello();
18 }
19 }
20
21 @Singleton
22 public class UseCase2{
23
24 private final TestService testService;
25 public UseCase2(TestService testService){
26 this.testService = testService;
27 }
28
29 void doIt(){
30 testService.sayHello();
31 }
32 }
En este ejemplo vemos cómo le indicamos a Micronaut que nuestra aplicación consta de tres clases y que queremos una sóla de cada una (al anotarlas como @Singleton)
Además, le decimos a Micronaut que en tiempo de compilación, antes de crear UseCase1 y UseCase2 tiene que crear TestService.
Así mismo una vez que se haya creado UseCase1 tiene que asignarle a la variable testService la instancia creada anteriormente (al anotarla con @Inject).
De la misma forma, cuando se vaya a llamar al constructor de UseCase2 se tiene que proporcionar la misma instancia de TestService que se ha usado en UseCase1
A lo largo del libro veremos alguna otra anotación, como @Controller, @Transactional pero son más fáciles de entender y casi autoexplicativas
El enfoque de Micronaut, a diferencia del de Spring, es que todo esto puede hacerlo en tiempo de compilación, es decir, Micronaut genera e inyecta código que resuelven todos estos detalles y los incorpora a nuestro “jar” como si los hubiéramos escrito nosotros mismos. Por el contrario, Spring utiliza las anotaciones para, en tiempo de ejecución descubrir estos detalles y resolver las dependencias entre los Singletons
Quarkus
Cuando uno habla de Micronaut es muy normal que alguien pregunte por Quarkus.
Quarkus es un framework que comparte muchas características e incluso historia con Micronaut, ya que fue creado casi al mismo tiempo y con una visión parecida.
La diferencia principal radica en la filosofía: Quarkus adopta el estándar MicroProfile/Jakarta EE y está muy optimizado para el ecosistema Kubernetes/Red Hat, mientras que Micronaut mantiene una sintaxis extremadamente cercana a Spring, facilitando la transición a desarrolladores acostumbrados al paradigma de Spring.
Aunque no lo he usado tanto como me gustaría Quarkus es otro framework muy maduro y con funcionalidades muy interesantes. Particularmente no lo he usado tanto porque no se puede usar Groovy, lenguaje que me apasiona, pero por lo demás es un framework tan bueno, en mi experiencia, como Micronaut.
ApiFirst con Micronaut
En una estrategia API-First, la especificación OpenAPI actúa como la fuente de verdad. Para llevar esto a producción de forma eficiente, necesitamos que la traducción del contrato OpenAPI a interfaces y controladores de Java no suponga una penalización de rendimiento en runtime.
El procesador de anotaciones de Micronaut no solo genera el servidor HTTP, sino que analiza la especificación OpenAPI durante la compilación para:
- Validar la consistencia de los tipos de datos antes de ejecutar la aplicación.
- Generar clases DTO y clientes HTTP sin añadir metadatos en runtime.
- Proporcionar documentación Swagger/OpenAPI estática.
En los próximos capítulos veremos la diferencia en la práctica, comparando la implementación directa basada en código con la generación automática mediante contratos.
