The Beanfactory Api

La API BeanFactory

La API BeanFactory proporciona la base subyacente de la funcionalidad IoC de Spring. Sus contratos específicos se utilizan sobre todo para integrarse con otras partes de Spring y con frameworks de terceros relacionados. Su implementación DefaultListableBeanFactory es un delegado clave dentro del contenedor de nivel superior GenericApplicationContext.

BeanFactory y las interfaces relacionadas —como BeanFactoryAware, InitializingBean y DisposableBean— son puntos de integración importantes para otros componentes del framework. Al no requerir anotaciones ni siquiera reflexión, permiten una interacción muy eficiente entre el contenedor y sus componentes.

Los beans de nivel de aplicación pueden utilizar esas mismas interfaces de devolución de llamada, pero normalmente prefieren la inyección declarativa de dependencias, ya sea mediante anotaciones o mediante configuración programática.

La API central de BeanFactory y su implementación DefaultListableBeanFactory no hacen suposiciones sobre el formato de configuración ni sobre las anotaciones de componentes que se vayan a utilizar.

Estas variantes se incorporan mediante extensiones —como XmlBeanDefinitionReader y AutowiredAnnotationBeanPostProcessor— y operan sobre objetos BeanDefinition compartidos como representación central de metadatos. Esta es la esencia de la flexibilidad y extensibilidad del contenedor de Spring.

¿BeanFactory o ApplicationContext?

Esta sección explica las diferencias entre los niveles de contenedor BeanFactory y ApplicationContext, así como sus implicaciones para el arranque.

Debes utilizar un ApplicationContext salvo que exista una buena razón para no hacerlo. GenericApplicationContext y su subclase AnnotationConfigApplicationContext son las implementaciones habituales para un arranque personalizado.

Son los puntos de entrada principales al contenedor central de Spring para los usos habituales:

  • Cargar archivos de configuración.
  • Activar una exploración del classpath.
  • Registrar mediante programación definiciones de beans y clases anotadas.
  • Registrar definiciones funcionales de beans.

Como ApplicationContext incluye toda la funcionalidad de un BeanFactory, por lo general se recomienda frente a un BeanFactory sin más, salvo en escenarios donde necesitas control total sobre el procesamiento de beans.

Dentro de un ApplicationContext —como GenericApplicationContext— se detectan por convención varios tipos de beans, por nombre o por tipo, especialmente los posprocesadores. En cambio, un DefaultListableBeanFactory simple no presupone la existencia de beans especiales.

Para muchas funcionalidades ampliadas del contenedor, como el procesamiento de anotaciones y la creación de proxies AOP, el punto de extensión BeanPostProcessor es esencial.

Si utilizas únicamente un DefaultListableBeanFactory simple, esos posprocesadores no se detectan ni activan de forma predeterminada. Esto puede resultar confuso, porque no existe un problema real en la configuración de los beans: el contenedor solo necesita un arranque completo con pasos de configuración adicionales.

Funcionalidad BeanFactory ApplicationContext
Instanciación y conexión de beans
Gestión integrada del ciclo de vida No
Registro automático de BeanPostProcessor No
Registro automático de BeanFactoryPostProcessor No
Acceso práctico a MessageSource para internacionalización No
Mecanismo integrado de publicación de ApplicationEvent No

Para registrar explícitamente un posprocesador de beans en un DefaultListableBeanFactory, debes llamar mediante programación a addBeanPostProcessor, como muestra el siguiente ejemplo:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

// Rellena la fábrica con definiciones de beans.
// Ahora registra las instancias necesarias de BeanPostProcessor.
factory.addBeanPostProcessor(new AutowiredAnnotationBeanPostProcessor());
factory.addBeanPostProcessor(new MyBeanPostProcessor());

// Ahora puedes comenzar a utilizar la fábrica.

Para aplicar un BeanFactoryPostProcessor a un DefaultListableBeanFactory simple, debes llamar a su método postProcessBeanFactory, como muestra el siguiente ejemplo:

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
reader.loadBeanDefinitions(new FileSystemResource("beans.xml"));

// Incorpora valores de propiedades desde un archivo Properties.
PropertySourcesPlaceholderConfigurer cfg =
		new PropertySourcesPlaceholderConfigurer();

cfg.setLocation(new FileSystemResource("jdbc.properties"));

// Ahora realiza la sustitución.
cfg.postProcessBeanFactory(factory);

En ambos casos, los pasos de registro explícito son incómodos. Por eso se prefieren las distintas variantes de ApplicationContext frente a un DefaultListableBeanFactory simple en aplicaciones basadas en Spring, especialmente cuando se depende de BeanFactoryPostProcessor y BeanPostProcessor para obtener funcionalidades ampliadas del contenedor en una configuración empresarial habitual.

AnnotationConfigApplicationContext incluye registrados todos los posprocesadores habituales de anotaciones. Además, puede incorporar otros procesadores internamente mediante anotaciones de configuración como @EnableTransactionManagement.

En el nivel de abstracción del modelo de configuración basado en anotaciones de Spring, la noción de posprocesadores de beans se convierte en un detalle interno del contenedor.