paint-brush
Usar el analizador de dependencias de Maven para eliminar dependencias no utilizadas es un consejo peligroso hoy en día.por@nfrankel
268 lecturas

Usar el analizador de dependencias de Maven para eliminar dependencias no utilizadas es un consejo peligroso hoy en día.

por Nicolas Fränkel4m2025/03/13
Read on Terminal Reader

Demasiado Largo; Para Leer

El estado actual del analizador Maven no ofrece ningún beneficio a los proyectos modernos de Spring Boot.
featured image - Usar el analizador de dependencias de Maven para eliminar dependencias no utilizadas es un consejo peligroso hoy en día.
Nicolas Fränkel HackerNoon profile picture


Recientemente, mi buen amigo Richard Fichtner recomendó utilizar el comando mvn dependency:analyze para deshacerse de las dependencias declaradas pero no utilizadas:

Aunque fue una gran idea hace años, hoy en día es un consejo peligroso. En esta publicación, quiero explicar qué hace el complemento y por qué no deberías usarlo, salvo en los proyectos más sencillos.

El comando mvn dependency:analyze

Maven utiliza una arquitectura de plugins; en el comando anterior, el plugin es maven-dependency-plugin . Un plugin aloja varios objetivos relacionados. En este caso, es analyze .


Analiza las dependencias de este proyecto y determina cuáles son: usadas y declaradas; usadas y no declaradas; no usadas y declaradas. Este objetivo está diseñado para usarse de forma independiente, por lo que siempre ejecuta la fase test-compile . En su lugar, utilice el objetivo dependency:analyze-only al participar en el ciclo de vida de la compilación.


De forma predeterminada, se utiliza maven-dependency-analyzer para realizar el análisis, con limitaciones debido al hecho de que funciona a nivel de bytecode, pero cualquier analizador se puede conectar a través del parámetro analyzer .


-- dependencia: analizar


maven-dependency-analyzer es un componente compartido de Maven. Su descripción es bastante clara:


Analiza las dependencias de un proyecto en busca de artefactos no declarados o no utilizados.

Advertencia : Dado que el análisis se realiza en el bytecode y no en el código fuente, algunos casos no se detectan, como constantes, anotaciones con retención solo del código fuente y enlaces en Javadoc. Esto puede generar resultados incorrectos cuando estos son los únicos usos de una dependencia.


El componente principal es ProjectDependencyAnalyzer , que utiliza ClassAnalyzer y DependencyAnalyzer .


-- analizador de dependencias de maven


La advertencia muestra claramente que funciona a nivel de bytecode . En particular, menciona explícitamente que no considera las anotaciones a nivel de fuente.

Arrancadores Spring Boot

Describí cómo diseñar tu propio starter de Spring Boot hace tiempo, y no ha cambiado mucho desde entonces. Si eres nuevo en el mundo de los starters de Spring Boot, aquí tienes un resumen.


SpringBoot se basa en clases de autoconfiguración. Estas clases son clases de configuración normales, es decir , contribuyen a las clases de la aplicación. Se pueden establecer criterios de activación específicos, como la presencia de una propiedad de Spring, pero estos no son específicos de la autoconfiguración.


He aquí un flujo muy simplificado:


Diagrama de secuencia simplificado de la autoconfiguración en Spring Boot


El JAR que viene automáticamente con Spring Boot es org.springframework.boot:spring-boot-autoconfigure . Puedes consultar el contenido de su META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports :


 ... org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration


A modo de ejemplo, aquí está RestClientAutoConfiguration :


 @AutoConfiguration(after = { HttpClientAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class }) //1 @ConditionalOnClass(RestTemplate.class) //2 @Conditional(NotReactiveWebApplicationCondition.class) //3 public class RestTemplateAutoConfiguration { // Class body }
  1. Establecer el orden de las clases de configuración automática
  2. Activar si la clase RestTemplate está en la ruta de clases
  3. Activar si no estamos en un contexto de aplicación web reactiva


Tenga en cuenta que el cargador de clases carga la clase RestTemplateAutoConfiguration sin problemas, independientemente de si la clase RestTemplate está en la ruta de clases o no. Spring aprovecha al máximo este mecanismo, como se vio anteriormente. De hecho, la resolución de las clases configuradas en las anotaciones se pospone hasta que se accede a ellas explícitamente .

Llevando el maven-dependency-analyzer a la era moderna

Los colaboradores diseñaron el analizador en 2007: así era como se veía entonces. Spring Boot se lanzó más tarde, en 2010. Por esta razón, el analizador no admitía la carga diferida de clases en las anotaciones. Cabe destacar que esto aún no es así; el proyecto no recibe mucha atención.


Al usar el complemento en un proyecto de Spring Boot, se producen muchos falsos positivos. Lo probé con un proyecto sencillo de Spring Boot, usando WebFlux y R2DBC en PostgreSQL.


Aquí hay un pequeño extracto del resultado cuando ejecuto mvn analyze:dependencies :


 [WARNING] Unused declared dependencies found: [WARNING] org.springframework.boot:spring-boot-starter-data-r2dbc:jar:3.4.0:compile [WARNING] org.testcontainers:postgresql:jar:1.20.4:test [WARNING] org.testcontainers:r2dbc:jar:1.20.4:test


Si elimino alguna de estas dependencias, las pruebas no se ejecutan.


¿Qué se necesita para que el analizador funcione con proyectos de Spring Boot? Analicemos el analizador.


Diagrama de clases del analizador


El complemento permite configurar otro analizador:


Especifique el analizador de dependencias del proyecto que se usará (componente Plexus role-hint). De forma predeterminada, se usa maven-dependency-analyzer. Para usarlo, debe declarar una dependencia para este complemento que contenga el código del analizador. El analizador debe tener un nombre de rol de Plexus declarado, el cual debe especificar aquí.


  • Tipo : java.lang.String

  • Desde : 2.2

  • Obligatorio : No

  • Propiedad del usuario : analyzer

  • Predeterminado : default


-- dependencia: analizar


Podemos crear un analizador general que reutilice el anterior pero agregue uno específico para Spring Boot.

Conclusión

El estado actual del analizador Maven no ofrece ninguna ventaja a los proyectos modernos de Spring Boot. El código existente se puede configurar e incluso ampliar. Sin embargo, necesitaríamos integrar mucha lógica de Spring Boot. Para proyectos de Quarkus y Micronaut, también necesitaríamos código dedicado.


No sé si vale la pena el tiempo y el esfuerzo. Si crees que sí, espero que esta entrada del blog te sirva como análisis inicial.


Para ir más allá:





Publicado originalmente en A Java Geek el 9 de marzo de 2025.