Estoy aprendiendo Spring 3 y parece que no entiendo la funcionalidad detrás <context:annotation-config>
y <context:component-scan>
.
Por lo que he leído parece que manejar diferentes anotaciones ( @Required
, @Autowired
etc vs @Component
, @Repository
, @Service
etc), sino también de lo que he leído se registran los mismos postprocesador frijol clases.
Para confundirme aún más, hay un annotation-config
atributo activado <context:component-scan>
.
¿Alguien puede arrojar algo de luz sobre estas etiquetas? Lo que es similar, lo que es diferente, es uno reemplazado por el otro, se completan, ¿necesito uno de los dos?
java
spring
configuration
annotations
spring-3
usuario938214097
fuente
fuente
component-scan
siempre que sea posible.Respuestas:
<context:annotation-config>
se utiliza para activar anotaciones en beans ya registrados en el contexto de la aplicación (sin importar si se definieron con XML o mediante escaneo de paquetes).<context:component-scan>
También puede hacer lo que<context:annotation-config>
hace, pero<context:component-scan>
también escanea paquetes para buscar y registrar beans dentro del contexto de la aplicación.Usaré algunos ejemplos para mostrar las diferencias / similitudes.
Comencemos con una configuración básica de tres beans de tipo
A
,B
yC
, conB
yC
siendo inyectadoA
.Con la siguiente configuración XML:
Cargar el contexto produce el siguiente resultado:
OK, este es el resultado esperado. Pero este es el "viejo estilo" de primavera. Ahora tenemos anotaciones, así que usemos esas para simplificar el XML.
Primero, vamos a conectar automáticamente las propiedades
bbb
yccc
en beanA
así:Esto me permite eliminar las siguientes filas del XML:
Mi XML ahora está simplificado a esto:
Cuando cargo el contexto obtengo el siguiente resultado:
OK, esto está mal! ¿Que pasó? ¿Por qué mis propiedades no tienen cableado automático?
Bueno, las anotaciones son una buena característica, pero por sí mismas no hacen nada en absoluto. Simplemente anotan cosas. Necesita una herramienta de procesamiento para encontrar las anotaciones y hacer algo con ellas.
<context:annotation-config>
al rescate. Esto activa las acciones para las anotaciones que encuentra en los beans definidos en el mismo contexto de aplicación donde se define.Si cambio mi XML a esto:
cuando cargo el contexto de la aplicación obtengo el resultado correcto:
OK, esto es bueno, pero eliminé dos filas del XML y agregué una. Esa no es una gran diferencia. La idea con anotaciones es que se supone que elimina el XML.
Así que eliminemos las definiciones XML y las reemplacemos todas con anotaciones:
Mientras que en el XML solo guardamos esto:
Cargamos el contexto y el resultado es ... Nada. No se crean beans, no hay beans con conexión automática. ¡Nada!
Eso es porque, como dije en el primer párrafo, el
<context:annotation-config />
único funciona en beans registrados dentro del contexto de la aplicación. Debido a que eliminé la configuración XML para los tres beans, no se creó ningún bean y<context:annotation-config />
no tiene "objetivos" para trabajar.Pero ese no será un problema para el
<context:component-scan>
que pueda escanear un paquete en busca de "objetivos" para trabajar. Cambiemos el contenido de la configuración XML a la siguiente entrada:Cuando cargo el contexto obtengo el siguiente resultado:
Hmmmm ... falta algo. ¿Por qué?
Si miras de cerca las clases, la clase
A
tiene un paquete,com.yyy
pero he especificado en el<context:component-scan>
paquete para usar,com.xxx
así que esto perdió por completo miA
clase y solo recogióB
yC
que están en elcom.xxx
paquete.Para solucionar esto, agrego este otro paquete también:
y ahora obtenemos el resultado esperado:
¡Y eso es! Ahora ya no tiene definiciones XML, tiene anotaciones.
Como ejemplo final, manteniendo las clases anotadas
A
,B
yC
y añadiendo lo siguiente en el XML, lo que vamos a llegar después de cargar el contexto?Aún obtenemos el resultado correcto:
Incluso si el bean para la clase
A
no se obtiene escaneando, las herramientas de procesamiento todavía se aplican<context:component-scan>
en todos los beans registrados en el contexto de la aplicación, incluso para losA
que se registraron manualmente en el XML.Pero, ¿qué pasa si tenemos el siguiente XML? ¿Obtendremos beans duplicados porque hemos especificado ambos
<context:annotation-config />
y<context:component-scan>
?No, no hay duplicaciones, nuevamente obtenemos el resultado esperado:
Esto se debe a que ambas etiquetas registran las mismas herramientas de procesamiento (
<context:annotation-config />
se pueden omitir si<context:component-scan>
se especifica), pero Spring se encarga de ejecutarlas solo una vez.Incluso si registra las herramientas de procesamiento usted mismo varias veces, Spring se asegurará de que hagan su magia solo una vez; este XML:
seguirá generando el siguiente resultado:
De acuerdo, eso es todo.
Espero que esta información junto con las respuestas de @Tomasz Nurkiewicz y @Sean Patrick Floyd sean todo lo que necesita para entender cómo
<context:annotation-config>
y<context:component-scan>
trabajar.fuente
Encontré este bonito resumen de qué anotaciones son recogidas por qué declaraciones. Al estudiarlo, encontrará que
<context:component-scan/>
reconoce un superconjunto de anotaciones reconocidas por<context:annotation-config/>
, a saber:@Component
`@Service
`@Repository
`@Controller
`@Endpoint
@Configuration
,@Bean
,@Lazy
,@Scope
,@Order
,@Primary
,@Profile
,@DependsOn
,@Import
,@ImportResource
Como puede ver,
<context:component-scan/>
lógicamente se extiende<context:annotation-config/>
con el escaneo de componentes CLASSPATH y las características de Java @Configuration.fuente
Spring te permite hacer dos cosas:
1. Autowiring
Por lo general, en applicationContext.xml se definen beans y otros beans se cablean utilizando métodos de construcción o configuración. Puede conectar beans utilizando XML o anotaciones. En caso de que utilice anotaciones, es necesario activar y anotaciones que hay que añadir
<context:annotation-config />
en applicationContext.xml . Esto simplificará la estructura de la etiqueta desde applicationContext.xml , ya que no tendrá que cablear manualmente beans (constructor o setter). Puede usar la@Autowire
anotación y los beans se cablearán por tipo.Un paso adelante para escapar de la configuración manual de XML es
2. Detección
automática La detección automática está simplificando el XML un paso más, en el sentido de que ni siquiera necesita agregar la
<bean>
etiqueta en applicationContext.xml . Simplemente marque los beans específicos con una de las siguientes anotaciones y Spring conectará automáticamente los beans marcados y sus dependencias al contenedor Spring. Las anotaciones son las siguientes: @Controller , @Service , @Component , @Repository . Al usar<context:component-scan>
y señalar el paquete base, Spring detectará automáticamente y conectará los componentes al contenedor Spring.Como conclusión:
<context:annotation-config />
se usa para poder usar la anotación @Autowired<context:component-scan />
se usa para determinar la búsqueda de beans específicos y el intento de autoconexión.fuente
<context:annotation-config>
activa muchas anotaciones diferentes en beans, ya sea que estén definidas en XML o mediante escaneo de componentes.<context:component-scan>
es para definir beans sin usar XMLPara más información, lea:
fuente
<context:component-scan>
, ¿no podré anular la definición de bean usando XML?<context:component-scan>
? ¿Pierdo algo si no uso el<context:annotation-config>
?¡La diferencia entre los dos es realmente simple!
Le permite usar anotaciones que están restringidas al cableado de propiedades y constructores solo de beans.
Donde como
Permite todo lo que
<context:annotation-config />
puede hacer, con la adición de la utilización de estereotipos por ejemplo, ..@Component
,@Service
,@Repository
. ¡Para que pueda conectar frijoles enteros y no solo restringidos a constructores o propiedades!fuente
<context:annotation-config>
: Escaneo y activación de anotaciones para beans ya registrados en spring config xml.<context:component-scan>
: Registro de frijoles +<context:annotation-config>
@Autowired y @Required son el nivel de propiedad de destino, por lo que el bean debe registrarse en el IOC de primavera antes de usar estas anotaciones. Para habilitar estas anotaciones, debe registrar los respectivos beans o incluir
<context:annotation-config />
. es decir, solo<context:annotation-config />
funciona con beans registrados.@Required habilita la
RequiredAnnotationBeanPostProcessor
herramienta de procesamiento@Autowired habilita la
AutowiredAnnotationBeanPostProcessor
herramienta de procesamientoNota: la anotación en sí no tiene nada que ver, necesitamos una herramienta de procesamiento , que es una clase debajo, responsable del proceso central.
@Repository, @Service y @Controller son @Component , y se dirigen a nivel de clase .
<context:component-scan>
escanea el paquete y busca y registra los beans, e incluye el trabajo realizado por<context:annotation-config />
.Migración de XML a anotaciones
fuente
La
<context:annotation-config>
etiqueta le dice a Spring que escanee la base de código para resolver automáticamente los requisitos de dependencia de las clases que contienen la anotación @Autowired.Spring 2.5 también agrega soporte para anotaciones JSR-250 como @Resource, @PostConstruct y @ PreDestroy. El uso de estas anotaciones también requiere que ciertos BeanPostProcessors se registren dentro del contenedor Spring. Como siempre, estos se pueden registrar como definiciones de beans individuales, pero también se pueden registrar implícitamente al incluir la
<context:annotation-config>
etiqueta en la configuración de primavera.Tomado de la documentación de Spring de la configuración basada en anotaciones
Spring proporciona la capacidad de detectar automáticamente clases 'estereotipadas' y registrar las definiciones de Bean correspondientes con el ApplicationContext.
Según el javadoc de org.springframework.stereotype :
Los estereotipos son anotaciones que denotan los roles de los tipos o métodos en la arquitectura general (a nivel conceptual, en lugar de implementación). Ejemplo: @Controller @Service @Repository, etc. Están destinados a ser utilizados por herramientas y aspectos (lo que constituye un objetivo ideal para los puntos de corte).
Para autodetectar tales clases de 'estereotipo',
<context:component-scan>
se requiere etiqueta.La
<context:component-scan>
etiqueta también le dice a Spring que escanee el código en busca de granos inyectables debajo del paquete (y todos sus subpaquetes) especificados.fuente
Solo resuelve las anotaciones
@Autowired
y@Qualifer
, eso es todo, se trata de la inyección de dependencia , hay otras anotaciones que hacen el mismo trabajo, creo que cómo@Inject
, pero todo a punto de resolver DI a través de anotaciones.Tenga en cuenta que, incluso cuando haya declarado el
<context:annotation-config>
elemento, debe declarar a su clase como un Bean de todos modos, recuerde que tenemos tres opciones disponibles<bean>
Ahora con
Hace dos cosas:
<context:annotation-config>
hace.Por lo tanto, si declaras
<context:component-scan>
, ya no es necesario declarar<context:annotation-config>
también.Eso es todo
Un escenario común era, por ejemplo, declarar solo un bean a través de XML y resolver el DI a través de anotaciones, por ejemplo
Solo hemos declarado los beans, nada al respecto ,
<constructor-arg>
y<property>
el DI está configurado en sus propias clases a través de @Autowired. Significa que los Servicios usan @Autowired para sus componentes de Repositorios y los Repositorios usan @Autowired para los componentes JdbcTemplate, DataSource, etc.fuente
intente con
<context:component-scan base-package="..." annotation-config="false"/>
, en su configuración @Service, @Repository, @Component funciona bien, pero @ Autowired, @ Resource y @Inject no funcionan.Esto significa que AutowiredAnnotationBeanPostProcessor no estará habilitado y Spring container no procesará las anotaciones de Autowiring.
fuente
El otro punto importante a tener en cuenta es que
context:component-scan
llama implícitamentecontext:annotation-config
a activar las anotaciones en beans. Bueno, si no deseacontext:component-scan
activar anotaciones implícitamente para usted, puede continuar configurando el elemento annotation-config decontext:component-scan
tofalse
.Para resumir:
fuente
<context:component-scan base-package="package name" />
:Esto se usa para decirle al contenedor que hay clases de bean en mi paquete, escanee esas clases de bean. Para escanear clases de bean por contenedor en la parte superior del bean, tenemos que escribir una de las anotaciones de tipo estéreo como la siguiente.
@Component
,@Service
,@Repository
,@Controller
<context:annotation-config />
:Si no queremos escribir la etiqueta del bean explícitamente en XML, entonces cómo el contenedor sabe si hay un cableado automático en el bean. Esto es posible mediante el uso de
@Autowired
anotaciones. Tenemos que informar al contenedor que hay un cableado automático en mi beancontext:annotation-config
.fuente
Una
<context:component-scan/>
etiqueta personalizada registra el mismo conjunto de definiciones de bean que se realiza, aparte de su responsabilidad principal de escanear los paquetes de Java y registrar las definiciones de bean desde el classpath.Si por alguna razón se evita este registro de definiciones de bean predeterminadas, la forma de hacerlo es especificar un atributo adicional "annotation-config" en el escaneo de componentes, de esta manera:
Referencia: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html
fuente
<context:annotation-config>
:Esto le dice a Spring que voy a usar frijoles anotados como spring bean y que se conectarán a través de
@Autowired
anotaciones, en lugar de declarar en el archivo Spring config xml.<context:component-scan base-package="com.test...">
:Esto le dice al contenedor Spring, dónde comenzar a buscar esos granos anotados. Aquí la primavera buscará todos los subpaquetes del paquete base.
fuente
puede encontrar más información en el archivo de esquema de contexto de primavera. siguiente está en spring-context-4.3.xsd
fuente
Como complemento, puede usarlo
@ComponentScan
para usarlo<context:component-scan>
en forma de anotación.También se describe en spring.io
Una cosa a tener en cuenta, si está utilizando Spring Boot, @Configuration y @ComponentScan pueden implicarse mediante el uso de la anotación @SpringBootApplication.
fuente