
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.
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 objetivodependency: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ámetroanalyzer
.
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 utilizaClassAnalyzer
yDependencyAnalyzer
.
La advertencia muestra claramente que funciona a nivel de bytecode . En particular, menciona explícitamente que no considera las anotaciones a nivel de fuente.
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:
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 }
RestTemplate
está en la ruta de clases
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 .
maven-dependency-analyzer
a la era modernaLos 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.
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
Podemos crear un analizador general que reutilice el anterior pero agregue uno específico para Spring Boot.
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.