BeanFactory vs ApplicationContext

Soy bastante nuevo en Spring Framework, he estado jugando con eso y poniendo algunas aplicaciones de muestra juntas con el propósito de evaluar Spring MVC para su uso en un próximo proyecto de la compañía. Hasta ahora, me gusta mucho lo que veo en Spring MVC, parece muy fácil de usar y lo aliento a escribir clases que sean muy amigables con las pruebas de la unidad.

Solo como ejercicio, estoy escribiendo un método principal para uno de mis proyectos de muestra / prueba. Una cosa sobre la que no tengo claro es sobre las diferencias exactas entre BeanFactory y ApplicationContext , ¿cuál es el adecuado para usar en qué condiciones?

Entiendo que ApplicationContext amplíe BeanFactory , pero si solo estoy escribiendo un método principal simple, ¿necesito la funcionalidad adicional que proporciona ApplicationContext ? ¿Y exactamente qué tipo de funcionalidad extra proporciona ApplicationContext ?

Además de responder “¿qué debo usar en un método main ()”, hay algún estándar o directriz en cuanto a qué implementación debería usar en tal escenario? ¿Debería escribirse mi método main () para que dependa de que la configuración del bean / aplicación esté en formato XML? ¿Es eso una suposición segura, o estoy bloqueando al usuario en algo específico?

¿Y esta respuesta cambia en un entorno web? Si alguna de mis clases necesitaba estar al tanto de Spring, ¿es más probable que necesiten ApplicationContext ?

Gracias por cualquier ayuda. Sé que muchas de estas preguntas probablemente se respondan en el manual de referencia, pero me está costando encontrar un desglose claro de estas dos interfaces y las ventajas y desventajas de cada una sin leer el manual con un peine de dientes finos.

Los documentos de spring son excelentes en esto: 3.8.1. BeanFactory o ApplicationContext? . Tienen una tabla con una comparación, voy a publicar un fragmento:

Fábrica de frijoles

  • Creación de instancias / cableado de frijoles

Contexto de la aplicación

  • Creación de instancias / cableado de frijoles
  • Registro automático de BeanPostProcessor
  • Registro automático de BeanFactoryPostProcessor
  • Acceso conveniente a MessageSource (para i18n)
  • Publicación de ApplicationEvent

Entonces, si necesita alguno de los puntos presentados en el lado del Contexto de la aplicación, debe usar ApplicationContext.

Para mí, la principal diferencia para elegir BeanFactory sobre ApplicationContext parece ser que ApplicationContext preinstantará todos los beans. De los documentos de Spring :

Spring establece las propiedades y resuelve las dependencias lo más tarde posible, cuando realmente se crea el bean. Esto significa que un contenedor Spring que se ha cargado correctamente puede generar una excepción más adelante cuando solicite un objeto si hay un problema al crear ese objeto o una de sus dependencias. Por ejemplo, el bean arroja una excepción como resultado de una propiedad faltante o no válida. Esta visibilidad potencialmente retrasada de algunos problemas de configuración es la razón por la cual las implementaciones de ApplicationContext preinstastan por defecto los beans singleton. A costa de un poco de tiempo inicial y memoria para crear estos beans antes de que sean realmente necesarios, descubres problemas de configuración cuando se crea el ApplicationContext, no más tarde. Todavía puede anular este comportamiento predeterminado para que los beans singleton se inicialicen de forma diferida, en lugar de preinstalarse.

Dado esto, inicialmente elegí BeanFactory para su uso en pruebas de integración / rendimiento ya que no quería cargar toda la aplicación para probar beans aislados. Sin embargo, y alguien me corrige si me equivoco, BeanFactory no es compatible con la configuración XML de classpath . Así que BeanFactory y ApplicationContext proporcionan una función crucial que yo quería, pero ninguno de los dos.

Cerca de lo que puedo decir, la nota en la documentación sobre la anulación del comportamiento de instanciación predeterminado se lleva a cabo en la configuración, y es per-bean, así que no puedo simplemente establecer el atributo “lazy-init” en el archivo XML o estoy atascado manteniendo una versión para prueba y otra para implementación.

Lo que terminé haciendo fue extender ClassPathXmlApplicationContext para cargar frijoles de forma perezosa para usar en pruebas como esta:

 public class LazyLoadingXmlApplicationContext extends ClassPathXmlApplicationContext { public LazyLoadingXmlApplicationContext(String[] configLocations) { super(configLocations); } /** * Upon loading bean definitions, force beans to be lazy-initialized. * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader) */ @Override protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException { super.loadBeanDefinitions(reader); for (String name: reader.getBeanFactory().getBeanDefinitionNames()) { AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) reader.getBeanFactory().getBeanDefinition(name); beanDefinition.setLazyInit(true); } } } 

Para agregar a lo que respondió Miguel Ping, aquí hay otra sección de la documentación que también responde esto:

Versión corta: use un ApplicationContext a menos que tenga una buena razón para no hacerlo. Para aquellos de ustedes que buscan un poco más de profundidad en cuanto al ‘pero por qué’ de la recomendación anterior, sigan leyendo.

(publicando esto para cualquier principiante de spring que pueda leer esta pregunta)

Spring proporciona dos tipos de contenedor IOC, uno es XMLBeanFactory y el otro es ApplicationContext .

 +---------------------------------------+-----------------+--------------------------------+ | | BeanFactory | ApplicationContext | +---------------------------------------+-----------------+--------------------------------+ | Annotation support | No | Yes | | BeanPostProcessor Registration | Manual | Automatic | | implementation | XMLBeanFactory | ClassPath/FileSystem/WebXmlApplicationContext| | internationalization | No | Yes | | Enterprise services | No | Yes | | ApplicationEvent publication | No | Yes | +---------------------------------------+-----------------+--------------------------------+ 

enter image description here

  • FileSystemXmlApplicationContext Beans cargados a través de la ruta completa.
  • Frijoles ClassPathXmlApplicationContext cargados a través de CLASSPATH
  • XMLWebApplicationContext y AnnotationConfigWebApplicationContext cargados a través del contexto de la aplicación web.
  • AnnotationConfigApplicationContext Cargando Spring beans desde la configuración basada en Annotation.

ejemplo:

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class); 
  • ApplicationContext es el contenedor inicializado por ContextLoaderListener o ContextLoaderServlet definido en un web.xml y ContextLoaderPlugin definido en struts-config.xml .
  1. ApplicationContext es la forma más preferida que BeanFactory

  2. En las nuevas versiones de Spring, BeanFactory se reemplaza con ApplicationContext . Pero todavía BeanFactory existe para la compatibilidad hacia atrás

  3. ApplicationContext extends BeanFactory y tiene los siguientes beneficios
    • admite la internacionalización de mensajes de texto
    • admite publicación de eventos para los oyentes registrados
    • acceso a recursos tales como URLs y archivos

Creo que es mejor usar siempre ApplicationContext, a menos que esté en un entorno móvil como ya lo dijo alguien más. ApplicationContext tiene más funcionalidades y definitivamente desea utilizar los PostProcessors como RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor y CommonAnnotationBeanPostProcessor, que lo ayudarán a simplificar sus archivos de configuración de Spring, y puede usar anotaciones como @Required, @PostConstruct, @Resource, etc. en sus beans .

Incluso si no usa todo lo que ofrece ApplicationContext, es mejor usarlo de todos modos, y luego si decide utilizar algunos recursos como mensajes o procesadores posteriores, o el otro esquema para agregar avisos transaccionales, etc. ya tendrá un ApplicationContext y no necesitará cambiar ningún código.

Si está escribiendo una aplicación independiente, cargue ApplicationContext en su método principal, utilizando ClassPathXmlApplicationContext, y obtenga el bean principal e invoque su ejecución () (o cualquier método) para iniciar su aplicación. Si está escribiendo una aplicación web, use ContextLoaderListener en web.xml para que cree el ApplicationContext y luego puede obtenerlo desde ServletContext, independientemente de si está utilizando JSP, JSF, JSTL, struts, Tapestry, etc. .

Además, recuerde que puede usar múltiples archivos de configuración Spring y puede crear ApplicationContext haciendo una lista de todos los archivos en el constructor (o incluyéndolos en el param-contexto para ContextLoaderListener), o simplemente puede cargar un archivo de configuración principal que tenga declaraciones de importación. Puede importar un archivo de configuración de Spring en otro archivo de configuración de Spring utilizando que es muy útil cuando crea programáticamente ApplicationContext en el método principal y carga solo un archivo de configuración de Spring.

  • BeanFactory: no es compatible con la dependency injection basada en anotaciones.
  • ApplicationContext: Admite Inyección de dependencia basada en anotaciones. – @ Autowired, @PreDestroy
  • BeanFactory: no es compatible
  • ApplicationContext: contextos de aplicación pueden publicar eventos en beans que están registrados como oyentes
  • BeanFactory: no es compatible con la forma de acceder a Message Bundle (internacionalización (I18N)
  • ApplicationContext: admite mensajes de internacionalización (I18N).
  • BeanFactory: No es compatible.
  • ApplicationContext: admite muchos servicios empresariales como el acceso JNDI, la integración EJB y la comunicación remota.
  • BeanFactory: por defecto es compatible con la carga lenta
  • ApplicationContext: Es por defecto compatible con la carga de Aggresive.

ApplicationContext: carga los granos de spring configurados en el archivo de configuración de spring y administra el ciclo de vida del bean de spring como y CUANDO EL CONTENEDOR COMIENZA. No esperará hasta que se llame a getBean (“springbeanref”) .

BeanFactory Carga los granos de spring configurados en el archivo de configuración de spring, administra el ciclo de vida del bean de spring cuando llamamos a getBean (“springbeanref”) . Así que cuando llamamos a getBean (“springbeanref”) en el momento de inicio del ciclo de vida del frijol .

En su mayor parte, se prefiere ApplicationContext a menos que necesite guardar recursos, como en una aplicación móvil.

No estoy seguro de depender del formato XML, pero estoy bastante seguro de que las implementaciones más comunes de ApplicationContext son las XML, como ClassPathXmlApplicationContext, XmlWebApplicationContext y FileSystemXmlApplicationContext. Esos son los únicos tres que he usado.

Si está desarrollando una aplicación web, es seguro decir que necesitará usar XmlWebApplicationContext.

Si desea que sus beans conozcan Spring, puede hacer que implementen BeanFactoryAware y / o ApplicationContextAware para que pueda usar BeanFactory o ApplicationContext y elegir qué interfaz implementar.

BeanFactory y ApplicationContext son formas de obtener frijoles de su contenedor de IOC de spring, pero aún existen algunas diferencias.

BeanFactory es el contenedor real que instancia, configura y administra una cantidad de beans. Estos beans generalmente colaboran entre sí y, por lo tanto, tienen dependencias entre ellos. Estas dependencias se reflejan en los datos de configuración utilizados por BeanFactory.

BeanFactory y ApplicationContext son ambas interfaces Java y ApplicationContext extiende BeanFactory. Ambos son configuraciones usando archivos de configuración XML. En resumen, BeanFactory proporciona funciones básicas de inversión de control ( IoC ) e dependency injections ( DI ), mientras que ApplicationContext proporciona funciones avanzadas .

Una BeanFactory está representada por la interfaz ” org.springframework.beans.factory ” Where BeanFactory, para la cual hay múltiples implementaciones.

 ClassPathResource resource = new ClassPathResource("appConfig.xml"); XmlBeanFactory factory = new XmlBeanFactory(resource); 

DIFERENCIA

  1. BeanFactory crea instancias de bean cuando se llama al método getBean () mientras ApplicationContext instancia un bean Singleton cuando se inicia el contenedor. No espera a que se llame a getBean ().

  2. BeanFactory no brinda soporte para la internacionalización, pero ApplicationContext brinda soporte para ello.

  3. Otra diferencia entre BeanFactory vs ApplicationContext es la capacidad de publicar eventos en beans que están registrados como listener.

  4. Una de las implementaciones populares de la interfaz BeanFactory es XMLBeanFactory, mientras que una de las implementaciones más populares de la interfaz ApplicationContext es ClassPathXmlApplicationContext .

  5. Si está utilizando el cableado automático y el uso de BeanFactory , debe registrar AutoWiredBeanPostProcessor mediante API, que puede configurar en XML si está utilizando ApplicationContext . En resumen, BeanFactory está bien para pruebas y uso no productivo, pero ApplicationContext es una implementación de contenedor más rica en características y debe ser favorecida sobre BeanFactory.

  6. BeanFactory de forma predeterminada es compatible con la carga diferida y ApplicationContext admite de forma predeterminada la carga de Aggresive .

Matriz de características de Bean Factory frente a contexto de aplicación obtenida de documentos de spring

enter image description here

Captura de pantalla de las características de BeanFacotry y ApplicationContext

La diferencia entre BeanFactory y ApplicationContext es la siguiente:

  1. BeanFactory usa la inicialización lenta, pero ApplicationContext usa la inicialización ansiosa. En el caso de BeanFactory, bean se crea cuando se llama al método getBeans (), pero bean se crea por adelantado en caso de ApplicationContext cuando se crea el objeto ApplicationContext.
  2. BeanFactory proporciona explícitamente un objeto de recurso usando syntax pero ApplicationContext crea y administra objetos de recursos por sí mismo.
  3. BeanFactory no es compatible con la internalización, pero ApplicationContext admite la internacionalización.
  4. Con la dependency injections basada en anotaciones de BeanFactory no se admite, pero la dependency injections basada en anotaciones es compatible con ApplicationContext.

Usando BeanFactory:

BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml")); Triangle triangle =(Triangle)beanFactory.getBean("triangle");

Usando ApplicationContext:

ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml") Triangle triangle =(Triangle)beanFactory.getBean("triangle");

Básicamente, podemos crear objetos contenedores de spring de dos maneras

  1. usando BeatFactory
  2. utilizando ApplicationContext

ambas son las interfaces

utilizando clases de implementación podemos crear objetos para contenedor de spring

llegando a las diferencias

BeanFactory

  1. No es compatible con la Inyección de dependencia basada en anotaciones.

  2. No es compatible con I18N

  3. Por defecto es compatible con la carga lenta

  4. no permite configurar múltiples archivos de configuración.

ex: BeanFactory context = new XmlBeanFactory (nuevo Recurso (“applicationContext.xml”));

ApplicationContext

  1. Soporte basado en la anotación de dependencia Inyección.-@Autowired, @PreDestroy

  2. Soporte I18N

  3. es Por defecto soporta carga de Aggresive.

  4. permite configurar múltiples archivos de configuración.

ex:
ApplicationContext context = new ClasspathXmlApplicationContext (“applicationContext.xml”);

a. Una diferencia entre la fábrica de beans y el contexto de la aplicación es que el ex único bean instancia cuando se llama al método getBean () mientras que ApplicationContext crea instancias de bean Singleton cuando se inicia el contenedor, no espera que se llame a getBean.

segundo.

 ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml"); 

o

 ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml}; 

Puede usar uno o más archivos xml según los requisitos de su proyecto. Como estoy aquí usando dos archivos xml, es decir, uno para los detalles de configuración para las clases de servicio, otras para las clases dao. Aquí ClassPathXmlApplicationContext es hijo de ApplicationContext.

do. BeanFactory Container es un contenedor básico, solo puede crear objetos e inyectar dependencias. Pero no podemos adjuntar otros servicios como seguridad, transacción, mensajería, etc. para proporcionar todos los servicios que tenemos para usar ApplicationContext Container.

re. BeanFactory no proporciona soporte para la internacionalización, es decir, i18n pero ApplicationContext proporciona soporte para ello.

mi. BeanFactory Container no es compatible con la característica de AutoScanning (Inyección de dependencia basada en la Anotación de soporte), pero ApplicationContext Container es compatible.

F. Beanfactory Container no creará un objeto bean hasta el momento de la solicitud. Significa que Beanfactory Container carga frijoles de forma perezosa. Mientras ApplicationContext Container crea objetos de Singleton bean en el momento de la carga solamente. Significa que hay una carga temprana.

gramo. Beanfactory Container admite solo dos ámbitos (singleton y prototipo) de los beans. Pero ApplicationContext Container es compatible con todo el scope de beans.

  1. BeanFactory utiliza un enfoque de inicialización lento mientras que ApplicationContext usa un enfoque de inicialización impaciente . es decir, BeanFactory crea un bean singleton solo cuando se le solicita, pero ApplicationContext crea todos los beans singleton en el momento de su propia inicialización.

  2. ApplicationContext crea y administra objetos de recursos por sí mismo, mientras que BeanFactory solía proporcionarse explícitamente un objeto de recurso con la syntax:

     ClassPathResource resource = new ClassPathResource("beans.xml"); XmlBeanFactory factory = new XmlBeanFactory(resource); // Here resource object is provided explicitly 
  3. ApplicationContext admite la internacionalización pero BeanFactory no.

  4. La inyección basada en la anotación no es compatible con BeanFactory, mientras que ApplicationContext admite el uso de la anotación @PreDestroy, @Autowired.

Refiera este documento de Spring Docs:

http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#context-introduction-ctx-vs-beanfactory

5.15.1 BeanFactory o ApplicationContext?

Use un ApplicationContext a menos que tenga una buena razón para no hacerlo.

Debido a que ApplicationContext incluye toda la funcionalidad de BeanFactory, generalmente se recomienda sobre BeanFactory, excepto en algunas situaciones, como en un Applet, donde el consumo de memoria puede ser crítico y unos pocos kilobytes adicionales pueden marcar la diferencia. Sin embargo, para la mayoría de las aplicaciones y sistemas empresariales típicos, ApplicationContext es lo que deseará usar. Spring 2.0 y posterior hace un uso intensivo del punto de extensión BeanPostProcessor (para efectuar proxys, etc.). Si usa solo BeanFactory simple, una buena cantidad de soporte como transacciones y AOP no tendrá efecto, al menos no sin algunos pasos adicionales de su parte. Esta situación podría ser confusa porque nada está realmente mal con la configuración.

Diferencia entre BeanFactory y ApplicationContext:

La interfaz org.springframework.beans.factory.BeanFactory y la interfaz org.springframework.context.ApplicationContext actúa como el contenedor IoC. La interfaz ApplicationContext está construida sobre la interfaz BeanFactory. Agrega algunas funciones adicionales a BeanFactory, como la integración simple con Spring’s AOP, manejo de recursos de mensajes (para I18N), propagación de eventos, contexto específico de capas de aplicaciones (por ejemplo, WebApplicationContext) para aplicaciones web. Por lo tanto, es mejor usar ApplicationContext que BeanFactory.

ApplicationContext es un hermano mayor de BeanFactory y esto es todo lo que BeanFactory ofrece, entre muchas otras cosas.

Además de las funcionalidades estándar del ciclo de vida org.springframework.beans.factory.BeanFactory, las implementaciones de ApplicationContext detectan e invocan los beans ApplicationContextAware así como los beans ResourceLoaderAware, ApplicationEventPublisherAware y MessageSourceAware.

En un escenario en tiempo real, la diferencia entre el contenedor Spring IOC Core (BeanFactory) y el contenedor Advanced J2EE (ApplicationContext) es la siguiente.

  1. BeanFactory creará objetos para los beans (es decir, para las clases POJO) mencionados en el archivo spring.xml ( ) solo cuando llame al método .getBean (), pero mientras que ApplicationContext crea los objetos para todo el beans ( si su ámbito no se menciona explícitamente como “Prototype”) configurado en spring.xml mientras se carga el archivo spring.xml.

  2. BeanFactory: (Contenedor diferido porque crea los objetos para los beans solo cuando llamas explícitamente desde el usuario / clase principal)

     /* * Using core Container - Lazy container - Because it creates the bean objects On-Demand */ //creating a resource Resource r = (Resource) new ClassPathResource("com.spring.resources/spring.xml"); //creating BeanFactory BeanFactory factory=new XmlBeanFactory(r); //Getting the bean for the POJO class "HelloWorld.java" HelloWorld worldObj1 = (HelloWorld) factory.getBean("test"); 

    ApplicationContext: (Contenedor ansioso porque crea los objetos de todos los beans simples mientras se carga el archivo spring.xml)

     ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml"); 
  3. Técnicamente, se recomienda el uso de ApplicationContext porque en las aplicaciones en tiempo real, los objetos Bean se crearán mientras la aplicación se inicia en el servidor. Esto reduce el tiempo de respuesta para la solicitud del usuario ya que los objetos ya están disponibles para responder.

Creo que vale la pena mencionar que desde Spring 3, si desea crear una fábrica, también puede usar la anotación @configuration combinada con el @scope adecuado

 @Configuration public class MyFactory { @Bean @Scope("prototype") public MyClass create() { return new MyClass(); } } 

Su fábrica debe ser visible en el contenedor Spring utilizando la anotación @ComponentScan o la configuración xml

Artículo de scopes de frijol spring desde el sitio de baeldung

utilice BeanFactory para aplicaciones que no sean web porque solo admite Singleton y Prototype bean-scopes.

Si bien el contenedor ApplicationContext es compatible con todos los bean-scopes, debe usarlo para aplicaciones web.

En resumen:

ApplicationContext incluye toda la funcionalidad de BeanFactory. En general, se recomienda utilizar el primero.

Hay algunas situaciones limitadas, como en una aplicación móvil, donde el consumo de memoria puede ser crítico.

En esos escenarios, puede ser justificable utilizar el BeanFactory más ligero. Sin embargo, en la mayoría de las aplicaciones empresariales, ApplicationContext es lo que deseará usar.

Más sobre:

Diferencia entre BeanFactory y ApplicationContext en spring – El blog de spring de Java desde lo básico