Diferencia entre vs

Estoy aprendiendo Spring 3 y parece que no aprecio la funcionalidad detrás de y .

Por lo que he leído, parecen manejar anotaciones diferentes (@Required, @Autowired etc vs @Component, @Repository, @Service, etc.) pero también de lo que he leído, registran las mismas clases de bean post processor.

Para confundirme aún más, hay un atributo de annotation-config en .

¿Alguien puede arrojar algo de luz sobre estas tags? Lo que es similar, lo que es diferente, es uno reemplazado por el otro, se completan el uno al otro, ¿necesito uno de ellos, ambos?

se usa 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).

también puede hacer lo que hace, pero también escanea paquetes para encontrar 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 granos de tipo A , B y C , con B y C inyectados en A

 package com.xxx; public class B { public B() { System.out.println("creating bean B: " + this); } } package com.xxx; public class C { public C() { System.out.println("creating bean C: " + this); } } package com.yyy; import com.xxx.B; import com.xxx.C; public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } } 

Con la siguiente configuración XML:

       

Cargando el contexto produce el siguiente resultado:

 creating bean B: com.xxx.B@c2ff5 creating bean C: com.xxx.C@1e8a1f6 creating bean A: com.yyy.A@1e152c5 setting A.bbb with com.xxx.B@c2ff5 setting A.ccc with com.xxx.C@1e8a1f6 

OK, este es el resultado esperado. Pero este es el “viejo estilo” de spring. Ahora tenemos anotaciones, así que permite usarlas para simplificar el XML.

Primero, permitamos que las propiedades bbb y ccc en el bean A vuelvan a conectar de la siguiente manera:

 package com.yyy; import org.springframework.beans.factory.annotation.Autowired; import com.xxx.B; import com.xxx.C; public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } @Autowired public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } @Autowired public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } } 

Esto me permite eliminar las siguientes filas del XML:

   

Mi XML ahora se simplifica a esto:

    

Cuando cargo el contexto obtengo el siguiente resultado:

 creating bean B: com.xxx.B@5e5a50 creating bean C: com.xxx.C@54a328 creating bean A: com.yyy.A@a3d4cf 

OK, esto está mal! ¿Que pasó? ¿Por qué mis propiedades no están auto conectadas?

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.

al rescate. Esto activa las acciones para las anotaciones que encuentra en los beans definidos en el mismo contexto de la aplicación donde se define.

Si cambio mi XML a esto:

     

cuando cargo el contexto de la aplicación obtengo el resultado adecuado:

 creating bean B: com.xxx.B@15663a2 creating bean C: com.xxx.C@cd5f8b creating bean A: com.yyy.A@157aa53 setting A.bbb with com.xxx.B@15663a2 setting A.ccc with com.xxx.C@cd5f8b 

OK, esto es lindo, pero eliminé dos filas del XML y agregué uno. Esa no es una gran diferencia. La idea con las anotaciones es que se supone que debe eliminar el XML.

Así que eliminemos las definiciones XML y reemplácelas por anotaciones:

 package com.xxx; import org.springframework.stereotype.Component; @Component public class B { public B() { System.out.println("creating bean B: " + this); } } package com.xxx; import org.springframework.stereotype.Component; @Component public class C { public C() { System.out.println("creating bean C: " + this); } } package com.yyy; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.xxx.B; import com.xxx.C; @Component public class A { private B bbb; private C ccc; public A() { System.out.println("creating bean A: " + this); } @Autowired public void setBbb(B bbb) { System.out.println("setting A.bbb with " + bbb); this.bbb = bbb; } @Autowired public void setCcc(C ccc) { System.out.println("setting A.ccc with " + ccc); this.ccc = ccc; } } 

Mientras que en el XML solo guardamos esto:

  

Cargamos el contexto y el resultado es … Nada. No se crean frijoles, ni frijoles se autoconectan. ¡Nada!

Eso es porque, como dije en el primer párrafo, el solo 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ó bean y no tiene “targets” para trabajar.

Pero eso no será un problema para que puede escanear un paquete para que funcionen los “targets”. Cambiemos el contenido de la configuración XML en la siguiente entrada:

  

Cuando cargo el contexto obtengo el siguiente resultado:

 creating bean B: com.xxx.B@1be0f0a creating bean C: com.xxx.C@80d1ff 

Hmmmm … falta algo. ¿Por qué?

Si miras a closelly en las clases, la clase A tiene el paquete com.yyy pero he especificado en el usar el paquete com.xxx por lo que com.xxx completamente mi clase A y solo recogí B y C están en el paquete com.xxx .

Para solucionar esto, agrego este otro paquete también:

  

y ahora obtenemos el resultado esperado:

 creating bean B: com.xxx.B@cd5f8b creating bean C: com.xxx.C@15ac3c9 creating bean A: com.yyy.A@ec4a87 setting A.bbb with com.xxx.B@cd5f8b setting A.ccc with com.xxx.C@15ac3c9 

¡Y eso es! Ahora ya no tienes definiciones XML, tienes anotaciones.

Como ejemplo final, manteniendo las clases anotadas A , B y C y agregando lo siguiente al XML, ¿qué obtendremos después de cargar el contexto?

   

Todavía obtenemos el resultado correcto:

 creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@1d64c37 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87 

Incluso si el bean para la clase A no se obtiene escaneando, sigue aplicando las herramientas de procesamiento en todos los beans registrados en el contexto de la aplicación, incluso para A que se registró manualmente en el XML.

Pero, ¿y si tenemos el siguiente XML, obtendremos beans duplicados porque hemos especificado tanto como ?

    

No, no hay duplicaciones, nuevamente obtenemos el resultado esperado:

 creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@1d64c37 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87 

Esto se debe a que ambas tags registran las mismas herramientas de procesamiento ( puede omitirse si 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:

        

todavía generará el siguiente resultado:

 creating bean B: com.xxx.B@157aa53 creating bean C: com.xxx.C@ec4a87 creating bean A: com.yyy.A@25d2b2 setting A.bbb with com.xxx.B@157aa53 setting A.ccc with com.xxx.C@ec4a87 

De acuerdo, eso sobre lo explota.

Espero que esta información junto con las respuestas de @Tomasz Nurkiewicz y @Sean Patrick Floyd sean todo lo que necesita para comprender cómo funcionan y .

Encontré este bonito resumen de las anotaciones que recogen las declaraciones. Al estudiarlo, encontrará que reconoce un superconjunto de anotaciones reconocidas por , a saber:

  • @Component , @Service , @Repository , @Controller , @Endpoint
  • @Configuration , @Bean , @Lazy , @Scope , @Order , @Primary , @Profile , @DependsOn , @Import , @ImportResource

Como puede ver, extiende lógicamente con el análisis del componente CLASSPATH y las características de Java @Configuration.

Spring te permite hacer dos cosas:

  1. Autocableado de frijoles
  2. Autodescubrimiento de frijoles

1. Autocableado
Por lo general, en applicationContext.xml define beans y otros beans se conectan utilizando métodos constructor o setter. Puede transferir beans utilizando XML o anotaciones. En caso de que use anotaciones, debe activar las anotaciones y debe agregar en applicationContext.xml . Esto simplificará la estructura de la etiqueta desde applicationContext.xml , ya que no tendrá que conectar manualmente beans (constructor o instalador). Puede usar la anotación @Autowire y los beans estarán cableados por tipo.

Un paso adelante para escapar de la configuración manual de XML es

2. Autodescubrimiento
Autodescubrimiento simplifica el XML un paso más allá, en el sentido de que ni siquiera necesita agregar la 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 de Spring. Las anotaciones son las siguientes: @Controller , @Service , @Component , @Repository . Al utilizar y señalar el paquete base, Spring detectará automáticamente y conectará los componentes al contenedor Spring.


Como conclusión:

  • se usa para poder usar la anotación @Autowired
  • se usa para determinar la búsqueda de beans específicos y el bash de autoenvío.

activa muchas anotaciones diferentes en beans, ya sea que estén definidas en XML o mediante escaneo de componentes.

es para definir beans sin usar XML

Para más información, lea:

  • 3.9. Configuración de contenedor basado en anotaciones
  • 3.10. Escaneo Classpath y componentes gestionados

¡La diferencia entre los dos es realmente simple !.

  

Le permite usar anotaciones que están restringidas a las propiedades de cableado y constructores solo de beans.

Donde como

  

Habilita todo lo que puede hacer, además de usar estereotipos, por ejemplo .. @Component , @Service , @Repository . ¡Así que puede cablear frijoles enteros y no limitarse a constructores o propiedades!

: Escanea y activa las anotaciones para los beans ya registrados en spring config xml.

: Bean registration +


@Autowired y @Required son objectives de nivel de propiedad, por lo que bean debe registrarse en el IOC de spring antes de utilizar estas anotaciones. Para habilitar estas anotaciones, debe registrar respectivos beans o incluir . es decir, funciona solo con beans registrados.

@Required habilita la herramienta de procesamiento RequiredAnnotationBeanPostProcessor
@Autowired habilita la herramienta de procesamiento AutowiredAnnotationBeanPostProcessor

Nota: 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 .

escanea el paquete y busca y registra los beans, e incluye el trabajo realizado por .

La 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 @Autowired annotation.

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 pueden registrarse como definiciones de bean individuales, pero también pueden registrarse implícitamente incluyendo la etiqueta en la configuración de spring.

Tomado de la documentación de Spring de Annotation Based Configuration


Spring proporciona la capacidad de detectar automáticamente clases “estereotipadas” y registrar BeanDefinitions correspondientes con ApplicationContext.

De acuerdo con javadoc de org.springframework.stereotype :

Los estereotipos son anotaciones que denotan los roles de los tipos o métodos en la architecture general (a nivel conceptual, en lugar de implementación). Ejemplo: @Controller @Service @Repository, etc. Estos están diseñados para ser utilizados por herramientas y aspectos (lo que los convierte en un objective ideal para los puntos de corte).

Para autodetectar tales clases de ‘estereotipos’, se requiere la etiqueta .

La etiqueta también le dice a Spring que escanee el código de los beans inyectables bajo el paquete (y todos sus subpaquetes) especificados.

  

Solo resuelve las anotaciones @Autowired y @Qualifer, eso es todo, se trata de la Inyección de dependencias , hay otras anotaciones que hacen el mismo trabajo, creo que cómo @Inject, pero todo a punto de resolver DI mediante anotaciones.

Tenga en cuenta, incluso cuando haya declarado el elemento , debe declarar su clase como un Bean de todos modos, recuerde que tenemos tres opciones disponibles

  • XML:
  • @Anotaciones: @Component, @Service, @Repository, @Controller
  • JavaConfig: @Bean

Ahora con

  

Hace dos cosas:

  • Escanea todas las clases anotadas con @Component, @Service, @Repository, @Controller y @Configuration y crea un Bean
  • Hace el mismo trabajo que hace .

Por lo tanto, si declara , ya no es necesario declarar .

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 sobre y , el DI se configura en sus propias clases a través de @Autowired. Significa que los Servicios usan @Autowired para sus componentes de Repositories y los Repositorios usan @Autowired para JdbcTemplate, DataSource etc..components.

  implicitly enables  

intente con , en su configuración @Service, @Repository, @Component funciona bien, pero @ Autowired, @ Resource e @Inject no funciona

Esto significa que AutowiredAnnotationBeanPostProcessor no se habilitará y el contenedor de Spring no procesará las anotaciones de Autowiring.

     

El otro punto importante a tener en cuenta es ese context:component-scan llama implícitamente al context:annotation-config para activar las anotaciones en los beans. Bien, si no desea el context:component-scan para activar anotaciones implícitamente para usted, puede continuar configurando el elemento de anotación-configuración del context:component-scan a false .

Para resumir:

     

Una etiqueta custom registra el mismo conjunto de definiciones de bean como lo hace, además de su responsabilidad principal de escanear los paquetes java y registrar las definiciones bean desde classpath.

Si por alguna razón se debe evitar este registro de las definiciones de bean predeterminadas, la forma de hacerlo es especificar un atributo adicional “annotation-config” en el componente-scan, de esta manera:

  

Referencia: http://www.java-allandsundry.com/2012/12/contextcomponent-scan-contextannotation.html

:

Esto se usa para decirle al contenedor que hay clases de beans en mi paquete que escanean esas clases de beans. Para escanear las clases de bean por contenedor en la parte superior del bean tenemos que escribir una de las anotaciones de tipo estereofónico como sigue.

@Component , @Service , @Repository , @Controller

:

Si no queremos escribir tags de bean explícitamente en XML, entonces cómo sabe el contenedor si hay un cableado automático en el bean. Esto es posible usando la anotación @Autowired . tenemos que informar al contenedor que hay cableado automático en mi bean por context:annotation-config .

contexto: anotación-config:

Esto le dice a Spring que no puedo usar frijoles ananados como el frijol de spring y que estos se cablearán a través de la anotación @Autowired, en lugar de declarar en el archivo Spring config xml.

contexto: componente-scan base-package = “com.test …”: Esto le dice al contenedor de Spring, donde comenzar a buscar esos beans anotados. Aquí la spring buscará todos los paquetes secundarios del