El contenedor Spring crea instancias y configura beans definidos en el contexto de su aplicación. También puede pedirle a la fábrica de beans que configure un objeto ya existente especificando el nombre de la definición del bean que contiene la configuración que desea aplicar. spring-aspects.jar contiene un aspecto basado en anotaciones que utiliza esta capacidad para realizar inyección de dependencia en cualquier objeto. El soporte está destinado a objetos creados fuera del control de cualquier contenedor. Los objetos de dominio a menudo entran en esta categoría porque a menudo se crean mediante programación usando el operador new o usando una herramienta de mapeo relacional de objetos (ORM) como resultado de una consulta de base de datos.

La anotación @Configurable marca la clase como adecuada para la configuración basada en Spring. En el caso más simple, puede usarlo como una anotación puramente de marcador, como se muestra en el siguiente ejemplo:

Java

package com.xyz.myapp.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable
public class Account {
    // ...
}
Kotlin

package com.xyz.myapp.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable
class Account {
    // ...
}

Cuando se usa de esta manera como token interfaz Spring configura nuevas instancias de un tipo anotado (en este caso Account) con una definición de bean (generalmente con alcance en el nivel de prototipo) con el mismo nombre que el nombre de tipo completo (com.xyz.myapp.domain.Account). Debido a que el nombre predeterminado de un bean es el nombre completo de su tipo, una manera conveniente de declarar una definición de prototipo es omitir el atributo id, como se muestra en el siguiente ejemplo:


<bean class="com.xyz.myapp.domain.Account" scope="prototype">
    <property name="fundsTransferService" ref="fundsTransferService"/>
</bean>

Si necesita especificar explícitamente el nombre de una definición de bean prototipo para su uso posterior, puede hacerlo directamente en la anotación. Como se muestra en el siguiente ejemplo:

Java

package com.xyz.myapp.domain;
import org.springframework.beans.factory.annotation.Configurable;
@Configurable("account")
public class Account {
    // ...
}
Kotlin

package com.xyz.myapp.domain
import org.springframework.beans.factory.annotation.Configurable
@Configurable("account")
class Account {
    // ...
}

Spring ahora buscará una definición de bean llamada account y la usará como definición para configurar nuevas instancias de Account.

También puedes utilice la detección y la vinculación automáticas para evitar especificar una definición de bean dedicada. Para que Spring aplique el descubrimiento y el cableado automáticos, utilice la propiedad autowire de la anotación @Configurable. Puede especificar @Configurable(autowire=Autowire.BY_TYPE) o @Configurable(autowire=Autowire.BY_NAME) para detectar y asociar automáticamente por tipo o por nombre, respectivamente. Como alternativa, es preferible especificar una inyección de dependencia explícita basada en anotaciones para sus beans anotados @Configurable a través de @Autowired o @Inject. anotaciones a nivel de campo o método.

Finalmente, puede habilitar la verificación de dependencia de Spring para referencias de objetos en un objeto recién creado y configurado usando el atributo dependencyCheck (por ejemplo, @Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)). Si este atributo se establece en true, una vez completada la configuración, Spring verificará que se hayan configurado todas las propiedades (que no sean primitivas ni colecciones).

Tenga en cuenta que usar el La anotación en sí no le da nada a sí mismo. Es el AnnotationBeanConfigurerAspect en spring-aspects.jar el que actúa cuando hay una anotación presente. Esencialmente, el aspecto dice: "Al regresar de inicializar un nuevo objeto de tipo anotado con @Configurable, configure el objeto recién creado usando Spring de acuerdo con las propiedades de la anotación". En este contexto, "inicialización" se refiere a instancias de objetos recién creadas (por ejemplo, objetos instanciados usando el operador new), así como a objetos Serializable que se deserializan (por ejemplo, a través de readResolve()).

Una de las frases clave en el párrafo anterior es "de hecho". En la mayoría de los casos, la semántica exacta de "al regresar de la inicialización de un nuevo objeto" será apropiada. En este contexto, "después de la inicialización" significa que las dependencias se inyectan después de que se construye el objeto. Esto significa que las dependencias no están disponibles para su uso en los cuerpos del constructor de clases. Si necesita inyectar dependencias antes de que los cuerpos del constructor comiencen a ejecutarse y, por lo tanto, hacerlas disponibles para su uso en el cuerpo del constructor, debe definir esto en la declaración de anotación @Configurable de la siguiente manera:

Java
@Configurable(preConstruction =
        true)
Kotlin
 @Configurable(preConstruction = true)

Para obtener más información sobre la semántica del lenguaje de los distintos tipos de sectores en AspectJ, puede encontrar en este apéndice de Guía de programación de AspectJ.

Para que esto funcione, los tipos anotados debe vincularse utilizando la herramienta de vinculación AspectJ. Para hacer esto, puede usar una tarea Ant o Maven en el momento de la compilación (consulte, por ejemplo, Guía del entorno de desarrollo de AspectJ), o vincular en el momento de la carga. Spring debe configurar el AnnotationBeanConfigurerAspect (para obtener una referencia a la fábrica de beans que se utilizará para configurar nuevos objetos). Si está utilizando una configuración basada en Java, puede agregar @EnableSpringConfigured a cualquier clase @Configuration como se muestra a continuación:

Java
@Configuration @EnableSpringConfigured clase pública AppConfig { }
Kotlin
@Configuration @EnableSpringConfigured class AppConfig { }

Si prefiere la configuración basada en XML, el espacio de nombres context en Spring define un elemento conveniente context:spring-configured, que se puede usar así:

<context:spring-configured/>

Si las instancias de objetos están marcadas con la anotación @Configurable se crea antes de que se haya configurado el aspecto, lo que da como resultado que aparezca un mensaje en el registro de depuración y la configuración del objeto falle. Un ejemplo sería un bean en una configuración de Spring que crea objetos de dominio cuando Spring lo inicializa. En este caso, puede utilizar el atributo depende-on del bean para indicar manualmente que el bean depende de un aspecto de configuración. El siguiente ejemplo muestra cómo utilizar el atributo depende de:


<bean id="myService"
        class="com.xzy.myapp.service.MyService"
        depende-on="org.springframework.beans.factory.aspectj. AnnotationBeanConfigurerAspect ">
    <!-- ... -->
</bean>
No habilitar el manejo de @Configurable a través del aspecto del configurador del bean, a menos que necesite usar su semántica en tiempo de ejecución. En particular, asegúrese de no utilizar la anotación @Configurable en clases de beans que estén registradas en el contenedor como Spring beans normales. Esto dará como resultado una inicialización doble: una a través del contenedor y otra a través del aspecto.

Objetos de prueba unitaria anotados con @Configurable

Uno de los propósitos de El soporte de annotation is @Configurable es la capacidad de realizar pruebas unitarias de objetos de dominio de forma independiente sin la molestia de realizar búsquedas secuenciales codificadas. Si los tipos marcados con la anotación @Configurable no han sido vinculados por AspectJ, entonces la anotación no tendrá ningún efecto en las pruebas unitarias. Puede establecer referencias de propiedad a un objeto simulado o a una función auxiliar en el objeto bajo prueba y continuar trabajando normalmente. Si los tipos con la anotación @Configurable han sido vinculados por AspectJ, aún podrá realizar pruebas unitarias fuera del contenedor como de costumbre, pero siempre que construya un objeto con @Configurable anotación, verá un mensaje de advertencia que indica que Spring no la ha configurado.

Trabajar con múltiples contextos de aplicación

AnnotationBeanConfigurerAspect, que se utiliza para implementar support @Configurable, es una instancia única de un aspecto de AspectJ. El alcance de una única instancia de un aspecto es el mismo que el alcance de los miembros static: para cada cargador de clases, hay una instancia de aspecto que define el tipo. Esto significa que si está definiendo múltiples contextos de aplicación dentro de la misma jerarquía del cargador de clases, debe pensar dónde definir el bean anotado con @EnableSpringConfigured y dónde colocar spring-aspects.jar. en el classpath.

Considere una configuración típica de una aplicación web Spring, que tiene un contexto de aplicación principal común que define servicios comerciales comunes, todo lo necesario para respaldar esos servicios y un contexto de aplicación secundaria para cada servlet. (que contiene definiciones específicas de este servlet). Todos estos contextos coexisten en la misma jerarquía del cargador de clases y, por lo tanto, AnnotationBeanConfigurerAspect solo puede contener una referencia a uno de ellos. En este caso, se recomienda definir el bean @EnableSpringConfigured en el contexto general (principal) de la aplicación. Esto identifica los servicios que quizás desee inyectar en los objetos de su dominio. La consecuencia de esto es que no podrá configurar objetos de dominio con referencias a beans definidos en contextos secundarios (específicos de servlet) utilizando el mecanismo de anotación @Configurable (que probablemente no querrá de todos modos).

Al implementar múltiples aplicaciones web en el mismo contenedor, asegúrese de que cada aplicación web cargue tipos desde spring-aspects.jar usando su propio cargador de clases (por ejemplo, colocando spring-aspects.jar en WEB-INF/lib). Si spring-aspects.jar solo se agrega al classpath general de todo el contenedor (y por lo tanto se carga un padre común cargador de clases), todas las aplicaciones web utilizarán la misma instancia de aspecto (lo que probablemente no desee).