A logo showing the text blog.marcnuri.com
English
Inicio»Java»Inyección de campos desaconsejada “Field injection is not recommended” – Spring IOC

Entradas Recientes

  • Fabric8 Kubernetes Client 7.2.0 está disponible!
  • Conectarse a un servidor MCP con JavaScript y AI SDK
  • Conectarse a un servidor MCP con JavaScript y LangChain.js
  • El Futuro de las Herramientas para Desarrolladores en la era de la IA
  • Conectarse a un servidor Model Context Protocol (MCP) con Java y LangChain4j

Categorías

  • Antiguo
  • Front-end
  • Go
  • Herramientas
  • Industria y negocios
  • Inteligencia Artificial
  • Java
  • JavaScript
  • Operaciones
  • Personal
  • Proyectos personales

Archivos

  • mayo 2025
  • abril 2025
  • marzo 2025
  • febrero 2025
  • enero 2025
  • diciembre 2024
  • noviembre 2024
  • agosto 2024
  • junio 2024
  • mayo 2024
  • abril 2024
  • marzo 2024
  • febrero 2024
  • enero 2024
  • diciembre 2023
  • noviembre 2023
  • octubre 2023
  • septiembre 2023
  • agosto 2023
  • julio 2023
  • junio 2023
  • mayo 2023
  • abril 2023
  • marzo 2023
  • febrero 2023
  • enero 2023
  • diciembre 2022
  • noviembre 2022
  • octubre 2022
  • agosto 2022
  • julio 2022
  • mayo 2022
  • marzo 2022
  • febrero 2022
  • enero 2022
  • diciembre 2021
  • noviembre 2021
  • octubre 2021
  • septiembre 2021
  • agosto 2021
  • julio 2021
  • diciembre 2020
  • octubre 2020
  • agosto 2020
  • junio 2020
  • mayo 2020
  • marzo 2020
  • febrero 2020
  • enero 2020
  • noviembre 2019
  • octubre 2019
  • julio 2019
  • diciembre 2018
  • agosto 2018
  • julio 2018
  • junio 2018
  • mayo 2018
  • marzo 2018
  • febrero 2018
  • noviembre 2017
  • octubre 2017
  • agosto 2017
  • julio 2017
  • enero 2017
  • julio 2016
  • enero 2016
  • diciembre 2015
  • noviembre 2015
  • diciembre 2014
  • marzo 2014
  • febrero 2011
  • junio 2008
  • mayo 2008
  • abril 2008
  • enero 2008
  • junio 2007
  • mayo 2007
  • abril 2007
  • marzo 2007

Inyección de campos desaconsejada “Field injection is not recommended” – Spring IOC

2018-03-10 en Java etiquetado Inyección de dependencias / Inversión de control (IoC) / Java / SOLID / Spring Framework por Marc Nuri | Última actualización: 2021-08-07
English version

Introducción

Tras la ejecución de alguna herramienta de análisis estático de código o analizando el código desde algún IDE, es posible muy probable haberse topado con un mensaje en relación a los campos @Autowired:

Field injection is not recommended
Field injection is not recommended (Captura de pantalla de alerta en IntelliJ IDEA)
Field injection is not recommended (Captura de pantalla de alerta en IntelliJ IDEA)

Esta publicación muestra los distintos tipos de inyección disponibles en Spring y cuáles son los patrones de uso recomendados para cada uno de ellos.

Tipos de Inyección

A pesar de que la documentación actual de Spring Framework (5.0.3) únicamente define dos tipos de inyección, en realidad hay tres:

  • Inyección de dependencias basada en el constructor (Constructor-based)
  • Inyección de dependencias basada en el setter (Setter-based)
  • Inyección de dependencias basada en campos (Field-based)

Esta última es la que hace que las herramientas de análisis de código muestren advertencias, a pesar de ser una de las formas de inyección más comúnmente aceptadas y utilizadas.

Incluso se puede apreciar el uso de este tipo de inyección en alguno de los tutoriales de Spring a pesar de ser algo desaconsejado en la documentación:

Spring guide with autowired field

Inyección de dependencias basada en el constructor (Constructor-based)

En la inyección de dependencias basada en el constructor, el constructor de la clase se anota con @Autowired e incluye un número variable de parámetros con los objetos a inyectar.

1@Component
2public class ConstructorBasedInjection {
3
4    private final InjectedBean injectedBean;
5
6    @Autowired
7    public ConstructorBasedInjection(InjectedBean injectedBean) {
8        this.injectedBean = injectedBean;
9    }
10
11}

La principal ventaja de la inyección basada en el constructor es que puedes declarar los campos inyectados como finales ya que se iniciarán durante la instanciación de la clase. Esto es muy aconsejable para declarar las dependencias obligatorias.

Inyección de dependencias basada en el setter (Setter-based)

En la inyección de dependencias basada en setter, los métodos tipo setter se anotan con @Autowired. El contenedor de Spring llamará a estos métodos una vez el Bean se haya instanciado para inyectar sus dependencias.

1@Component
2public class ConstructorBasedInjection {
3
4    private InjectedBean injectedBean;
5
6    @Autowired
7    public void setInjectedBean(InjectedBean injectedBean) {
8        this.injectedBean = injectedBean;
9    }
10
11}

Inyección de dependencias basada en campos (Field-based)

En la inyección de dependencias basada en campos, los propios campos de la clase se anotan con @Autowired. El contenedor de Spring asignará el valor a estos campos una vez la clase se haya instanciado.

1@Component
2public class ConstructorBasedInjection {
3
4    @Autowired
5    private InjectedBean injectedBean;
6
7}

Como puede observarse, esta es la forma más limpia de inyectar las dependencias ya que nos evita añadir código extra para setters/getters y no es necesario declarar un constructor en la clase. El código se ve limpio y conciso, pero tal como el inspector de código nos advierte, este enfoque tiene algunos inconvenientes.

Desventajas de la inyección de dependencias basada en campos (Field-based)

Contraviene la declaración de campos inmutables

La inyección de dependencias basada en campos no funciona en variables que se declaran como finales/inmutables, ya que estos campos deberían de instanciarse al mismo tiempo que lo hace la clase que los contiene. La única forma de declarar dependencias finales/inmutables es a través de la inyección de dependencias basada en el constructor.

Facilita la transgresión/incumplimiento del principio de responsabilidad única

En programación orientada a objetos, el acrónimo SOLID define 5 principios de diseño que facilitarán el desarrollo de código comprensible, flexible y fácil de mantener.

La S en SOLID representa el principio de responsabilidad única, “Single responsibility principle” en inglés. Este principio recomienda que una clase debe ser responsable exclusivamente de una parte de la funcionalidad de la aplicación y dicha clase debe de encapsular esta responsabilidad en su totalidad, por lo que todos sus servicios deberían de estar relacionados estrechamente con esta misma funcionalidad.

La inyección basada en dependencias, facilita muchísimo la inyección y además lo hace de forma elegante, por lo que es muy fácil terminar con una clase con muchas dependencias sin que nada resulte sospechoso. Si en lugar de este tipo de inyección se hubiese elegido la inyección de dependencias basada en el constructor, a medida que se hubiesen añadido dependencias el constructor se habría hecho más y más grande y el código empezaría a apestar, enviando señales claras de que algo está mal.

Tener un constructor con más de diez parámetros es un claro síntoma de que la clase tiene demasiados colaboradores y de que probablemente es hora de comenzar a dividirla en partes mas pequeñas y fáciles de mantener.

Por tanto, aunque evidentemente, la inyección de dependencias basada en campos no es la responsable directa de romper el principio de responsabilidad única, ayuda a corromper el principio al ocultar señales que de otro modo se verían claramente.

Elevado acoplamiento con el contenedor encargado de la inyección de dependencias

El principal motivo para el uso de inyección de dependencias basada en campos es para evitar tener que añadir código adicional en el constructor de la clase o añadiendo getters y setters. En el fondo, esto implica que la única forma en la que a estos campos se les puede dar un valor es a través del contenedor de Spring y qué este los inyecte mediante reflexión. De otro modo, lo campos permanecerían con valor null y el objeto instanciado de esta clase estaría roto y sería inservible.

El patrón de diseño para la inyección de dependencias establece una separación entre la creación de las dependencias de una clase y la creación de la propia clase. El patrón asigna esta responsabilidad a un inyector de clases, permitiendo a la aplicación estar desacoplada y seguir el principio de responsabilidad única así como el de Inversión de la dependencia (SOLID de nuevo). Por lo tanto, al emplear @Autowire para inyectar directamente sobre los campos, se pierde el desacoplamiento que se busca ya que en lugar de tener acoplada la clase ahora tenemos acoplado el inyector de clases (en este caso Spring), ya que sin este inyector concreto la clase no podría tener estos campos inyectados y por tanto sería inservible fuera del contenedor de Spring.

Esto significa que si queremos utilizar la clase fuera del contenedor de aplicaciones, por ejemplo durante los tests unitarios, nos vemos obligados a utilizar el contenedor de Spring para instanciar la clase, ya que no existe otro modo posible de dar valor a estos campos @Autowired (salvo reflexión).

Dependencias ocultas

El empleo del patrón de inyección de dependencias implica que las clases afectadas muestren de forma pública estas dependencias de algún modo. Bien mediante su exposición en el constructor como parámetros cuando son obligatorias, o bien en algún método (setters) cuando son opcionales. Cuando se emplea la inyección de dependencias basada en campos, la clase está de forma inherente ocultando sus dependencias al mundo exterior.

Conclusión

Hemos visto las distintas desventajas de la inyección basada en campos y cómo esta debe de evitarse en la medida de lo posible a pesar de resultar elegante y sencilla. El procedimiento recomendado es el de emplear la inyección basada en el constructor cuando se trate de dependencias obligatorias permitiendo a estas declararlas como inmutables y previniendo que puedan tener un valor null. Y por otro lado emplear la inyección de dependencias basada en el setter cuando se trate de dependencias opcionales.

Una imagen de jeringuillas para simbolizar la inyección de dependencias
Una imagen de jeringuillas para simbolizar la inyección de dependencias
Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Comentarios en "Inyección de campos desaconsejada “Field injection is not recommended” – Spring IOC"

  • Avatar for Tomás
    Tomás
    2018-11-22 19:04
    Excelente articulo, Lo busque porque justo esta viendo un tutorial de TDD y me surgio la pregunta de porque no usar la inyeccion sobre los campos en vez de utilizar le constructor.
    La teoria, es perfecta y me quedo super claro.
    Concuerdo en todo, muchas gracias
  • Avatar for Manuel
    Manuel
    2019-03-21 23:10
    Excelente explicación. Fácil de leer y entender.
    Gracias!!
  • Avatar for Gonzalo Castillo
    Gonzalo Castillo
    2019-04-19 13:57
    Muy buena explicación me ha ayudado mucho a aclarar estos conceptos. Sin embargo aun hay algo que me incomoda del @Autowired incluso si lo hago como setter debido a que la anotación es parte del framework de Spring por o que de cualquier forma estamos haciendo la clase dependiente de al menos tener Spring cargado en las librerías. Si esta anotación fuese parte de Java seria perfecto!

    Para solventar eso he estado utilizando @Resoruce en vez de @Autowired ya que esta si es parte del core de Java y al menos en mis proyectos Spring Boot estas estan siendo correctamente inyectados por Spring. No se si esto tendrá alguna desventaja, pero de omento me ha servido.
    • Avatar for Marc Nuri
      Marc Nuri
      2019-05-15 12:43
      Sí, @Resource, @Inject y @Autowired son mutuamente intercambiables (aunque con algunos matices). Cuanto más agnóstica la anotación, mejor, siempre facilitará la migración o refactorización del código.
  • Avatar for Nacho
    Nacho
    2020-07-14 08:30
    Muchas gracias por el post, muy didáctico y claro.

Navegador de artículos
Spring Data MongoDB: Implementación de un repositorio a medidaDocker: Configurando un contenedor como un servicio de Linux
© 2007 - 2025 Marc Nuri