BeanFactory vs ApplicationContext


235

Soy bastante nuevo en Spring Framework, he estado jugando con él y reuniendo algunas aplicaciones de muestra con el fin 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 alienta a escribir clases que sean muy fáciles de realizar en las pruebas unitarias.

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

Entiendo que se ApplicationContextextiende BeanFactory, pero si solo estoy escribiendo un método principal simple, ¿necesito la funcionalidad adicional que ApplicationContextproporciona? ¿Y exactamente qué tipo de funcionalidad adicional ApplicationContextproporciona?

Además de responder "¿qué debo usar en un método main ()", ¿existen estándares o pautas en cuanto a qué implementación debo usar en tal escenario? ¿Debería escribirse mi método main () para que dependa de que la configuración de bean / aplicación esté en formato XML? ¿Es 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 necesita estar al tanto de Spring, ¿es más probable que la necesiten ApplicationContext?

Gracias por cualquier ayuda. Sé que muchas de estas preguntas probablemente se respondan en el manual de referencia, pero me resulta difícil 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.

Respuestas:


209

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

Fábrica de frijoles

  • Frijoles instanciación / cableado

Contexto de aplicación

  • Frijoles instanciación / cableado
  • Registro automático de BeanPostProcessor
  • Registro automático de BeanFactoryPostProcessor
  • Acceso conveniente a MessageSource (para i18n)
  • Aplicación Publicación del evento

Por lo tanto, si necesita alguno de los puntos presentados en el lado del contexto de la aplicación, debe usar el contexto de la aplicación.


3
BeanFactory es liviano, pero si va a usar Spring "de verdad", también puede usar el ApplicationContext: hay muy poca sobrecarga si no usa sus características sofisticadas, pero aún están disponibles para si / cuando los usas.
MetroidFan2002

2
¿Qué significa cuando dices "registro automático de BeanPostPorcessor"? ¿Significa que la clase no tiene que implementar esa interfaz?
Abidi

2
ApplicationContext admite AOP contra BeanFactory.
ininprsr

1
Con BeanFactorypodemos pasar parámetros de constructor dinámicamente pero con ApplicationContextno podemos hacer eso.
Príncipe mestizo

1
Una nota importante de la documentación de Spring vinculada: "Las versiones de Spring 2.0 y superiores hacen un uso intensivo del punto de extensión BeanPostProcessor (para efectuar proxy y similares), y si está utilizando un BeanFactory simple, entonces una buena cantidad de soporte, como transacciones y AOP no surtirá efecto (al menos no sin algunos pasos adicionales de su parte) ".
mark.monteiro

52

Spring proporciona dos tipos de contenedor de COI, uno es XMLBeanFactoryy 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                            |
+---------------------------------------+-----------------+--------------------------------+

ingrese la descripción de la imagen aquí

  • FileSystemXmlApplicationContext Frijoles cargados a través del camino completo.
  • ClassPathXmlApplicationContext Frijoles cargados a través del CLASSPATH
  • XMLWebApplicationContexty AnnotationConfigWebApplicationContextbeans cargados a través del contexto de la aplicación web.
  • AnnotationConfigApplicationContext Cargando Spring beans desde la configuración basada en Anotación.

ejemplo:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContextes el contenedor inicializado por a ContextLoaderListenero ContextLoaderServletdefinido en a web.xmly ContextLoaderPlugindefinido en struts-config.xml.

Nota : XmlBeanFactoryestá en desuso a partir de Spring 3.1 a favor de DefaultListableBeanFactoryy XmlBeanDefinitionReader.


2
its AnnotationConfigApplicationContext not -AnnotationConfigWebApplicationContext- debajo de ClassPathXmlApplicationContext en el diagrama
Akhil Jain

48

Para mí, la diferencia principal para elegir BeanFactorymás ApplicationContextparece ser que ApplicationContextse pre-instantiate todos los granos. De los documentos de primavera :

Spring establece propiedades y resuelve dependencias lo más tarde posible, cuando el bean se crea realmente. Esto significa que un contenedor Spring que se ha cargado correctamente más tarde puede generar una excepción cuando solicita un objeto si hay un problema al crear ese objeto o una de sus dependencias. Por ejemplo, el bean produce una excepción como resultado de una propiedad que falta o no es válida. Esta visibilidad potencialmente retrasada de algunos problemas de configuración es la razón por la cual las implementaciones de ApplicationContext por defecto pre-instancian beans singleton. A costa de un tiempo inicial y memoria para crear estos beans antes de que realmente se necesiten, descubre 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 ser instanciados previamente.

Dado esto, inicialmente elegí BeanFactoryusar 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, BeanFactoryno admite la classpathconfiguración XML. Entonces, BeanFactoryy ApplicationContextcada uno proporciona una característica crucial que quería, pero ninguno de los dos.

Por lo que puedo decir, la nota en la documentación sobre cómo anular el comportamiento predeterminado de instanciación tiene lugar en la configuración, y es por bean, por lo 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 ClassPathXmlApplicationContextpara cargar frijoles perezosamente 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);
        }
    }

}

2
Yo diría que si sus pruebas unitarias están cargando su contexto Spring completo, no son "pruebas unitarias", sino pruebas de integración.
mate b

1
Buen punto. En mi caso, en realidad necesitaba cargar beans desde el contexto para las pruebas de rendimiento e integración, y escribí "pruebas unitarias" por costumbre. He editado mi respuesta en consecuencia.
Lyle

2
BeanFactory doesn't support classpath XML configuration.Creo que sí: stackoverflow.com/questions/5231371/…
Xtreme Biker

29

Para agregar a lo que respondió Miguel Ping, aquí hay otra sección de la documentación que también responde a 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.

(publicar esto para cualquier futuro principiante de primavera que pueda leer esta pregunta)


19
  1. ApplicationContext es la forma más preferida que BeanFactory

  2. En las nuevas versiones de Spring BeanFactoryse reemplaza con ApplicationContext. Pero todavía BeanFactoryexiste para la compatibilidad con versiones anteriores.

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

13

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

BeanFactory Carga spring beans configurados en el archivo de configuración de spring, gestiona el ciclo de vida del spring bean cuando llamamos a getBean ("springbeanref") . Así que cuando llamamos a getBean ("springbeanref") en el momento del inicio del ciclo de vida de spring bean .


12

Creo que es mejor usar siempre ApplicationContext, a menos que esté en un entorno móvil como ya dijo alguien más. Application Context tiene más funcionalidad y que debe de utilizar los Postprocesadores como RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor y CommonAnnotationBeanPostProcessor, lo que ayudará a simplificar sus archivos de configuración de la primavera, y se puede utilizar anotaciones tales como @Required, @PostConstruct, @Resource, etc en sus granos .

Incluso si no usa todas las cosas que ofrece ApplicationContext, es mejor usarlas de todos modos, y luego si decide usar algunas cosas de recursos como mensajes o procesadores posteriores, o el otro esquema para agregar consejos transaccionales y tal, usted ya tendrá un ApplicationContext y no necesitará cambiar ningún código.

Si está escribiendo una aplicación independiente, cargue el ApplicationContext en su método principal, utilizando un 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 pueda obtenerlo del ServletContext, independientemente de si está utilizando JSP, JSF, JSTL, struts, Tapestry, etc. .

Además, recuerde que puede usar varios archivos de configuración de Spring y puede crear ApplicationContext enumerando todos los archivos en el constructor (o enumerándolos en el parámetro de contexto para ContextLoaderListener), o simplemente puede cargar un archivo de configuración principal que tiene declaraciones de importación. Puede importar un archivo de configuración de Spring a otro archivo de configuración de Spring utilizando <import resource = "otherfile.xml" />, que es muy útil cuando crea ProgramContext mediante el método principal y carga solo un archivo de configuración de Spring.


6

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 estén al tanto de Spring, puede hacer que implementen BeanFactoryAware y / o ApplicationContextAware para eso, de modo que pueda usar BeanFactory o ApplicationContext y elegir qué interfaz implementar.


Esta es una sección relevante de la documentación Como ApplicationContextincluye toda la funcionalidad de la BeanFactory, generalmente se recomienda que se use con preferencia a la BeanFactory, excepto en algunas situaciones limitadas como en un Applet, donde el consumo de memoria podría ser crítico y algunos kilobytes adicionales podrían Hacer la diferencia. Sin embargo, para la mayoría de las aplicaciones y sistemas empresariales 'típicos', elApplicationContext es lo que querrá usar.
M. Atif Riaz

6

Las diferencias entre BeanFactory y ApplicationContext son las siguientes:

  1. BeanFactory usa una inicialización diferida, pero ApplicationContext usa una inicialización ansiosa. En el caso de BeanFactory, el bean se crea cuando se llama al método getBeans (), pero el bean se crea por adelantado en el caso de ApplicationContext cuando se crea el objeto ApplicationContext.
  2. BeanFactory proporciona explícitamente un objeto de recurso utilizando la sintaxis, pero ApplicationContext crea y gestiona objetos de recurso por sí solo.
  3. BeanFactory no admite la internacionalización, pero ApplicationContext admite la internacionalización.
  4. Con BeanFactory, la inyección de dependencia basada en anotaciones no es compatible, pero la inyección de dependencia 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)context.getBean("triangle");

5

BeanFactory y ApplicationContext son formas de obtener frijoles de su contenedor Spring IOC , pero aún hay alguna diferencia.

BeanFactory es el contenedor real que crea instancias, configura y gestiona varios beans. Estos beans normalmente 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 interfaces Java y ApplicationContext extiende BeanFactory. Ambos son de configuración utilizando archivos de configuración XML. En resumen, BeanFactory proporciona funciones básicas de Inversión de control ( IoC ) e Inyección de dependencias ( DI ), mientras que ApplicationContext proporciona funciones avanzadas .

Un BeanFactory está representado por la interfaz " org.springframework.beans.factory " Donde BeanFactory, para el que hay múltiples implementaciones.

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

DIFERENCIA

  1. BeanFactory instancia el bean cuando llamas al método getBean () mientras ApplicationContext instancia el bean Singleton cuando se inicia el contenedor, no espera a que se llame a getBean ().

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

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

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

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

  6. BeanFactory por defecto su apoyo Lazy carga y Application Context por el apoyo defecto Aggresive carga.


¿Puede explicar su # 1 más claramente? Si he definido un bean singleton en mi archivo de configuración de Spring, el contenedor Spring creará un singleton de lo mismo, ¿qué importa si BeanFactory o ApplicationContext están allí?
pjj


3

a. Una diferencia entre la fábrica de beans y el contexto de la aplicación es que el anterior solo instancia el bean cuando llama al método getBean () mientras que ApplicationContext instancia el bean Singleton cuando se inicia el contenedor. No espera a que se llame a getBean.

si.

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 detalles de configuración para clases de servicio y otro para clases de dao. Aquí ClassPathXmlApplicationContext es hijo de ApplicationContext.

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

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

mi. BeanFactory Container no admite la función de AutoScanning (Inyección de dependencias basada en anotaciones de soporte), pero ApplicationContext Container sí lo admite.

F. Beanfactory Container no creará un objeto bean hasta el momento de la solicitud. Significa que Beanfactory Container carga frijoles perezosamente. Mientras ApplicationContext Container crea objetos de bean Singleton 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 admite todo el alcance de beans.


Los puntos a y f son iguales. Se pueden combinar juntos.
dhana1310

3

Básicamente, podemos crear objetos contenedor de resorte de dos maneras

  1. usando BeanFactory.
  2. usando ApplicationContext.

ambas son las interfaces,

Usando clases de implementación podemos crear objetos para el contenedor Spring

llegando a las diferencias

BeanFactory:

  1. No admite la inyección de dependencia basada en anotaciones.

  2. No es compatible con I18N.

  3. Por defecto es compatible con la carga diferida.

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

ej .: contexto BeanFactory = nuevo XmlBeanFactory (nuevo recurso ("applicationContext.xml"));

ApplicationContext

  1. Inyección de dependencia basada en anotaciones de soporte.-@Autowired, @PreDestroy

  2. Soporte I18N

  3. Su soporte predeterminado es la carga agresiva.

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

ej:
contexto de ApplicationContext = nuevo ClasspathXmlApplicationContext ("applicationContext.xml");


1

Consulte 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, el ApplicationContext es lo que querrá usar. Spring 2.0 y posterior hace un uso intensivo del punto de extensión BeanPostProcessor (para efectuar proxy y así sucesivamente). Si usa solo un BeanFactory simple, una cantidad justa 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 en realidad no hay nada malo con la configuración.


1

ApplicationContext es un gran hermano de BeanFactory y esto sería todo lo que se proporciona BeanFactory además de muchas otras cosas.

Además de las capacidades 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.


1

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 ( <bean></bean>) solo cuando llame al método .getBean (), pero mientras que ApplicationContext crea los objetos para todos los beans ( <bean></bean>si su alcance no es mencionado explícitamente como "Prototipo") configurado en spring.xml al cargar el archivo spring.xml.

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

    /*
     * 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 por crear los objetos de todos los beans singleton mientras se carga el archivo spring.xml)

    ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
  3. Técnicamente, se recomienda usar ApplicationContext porque en aplicaciones en tiempo real, los objetos de 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.


Stack Overflow no es un foro, por lo que he editado su respuesta para responder más directamente a la pregunta y evitar invitar a la discusión.
Jeffrey Bosboom


0

utilice BeanFactory para aplicaciones que no sean web porque solo admite ámbitos de bean Singleton y Prototype.

Si bien el contenedor ApplicationContext admite todos los ámbitos de bean, debería usarlo para aplicaciones web.


0

En resumen:

El contexto de la aplicación incluye toda la funcionalidad de la BeanFactory. Generalmente se recomienda usar 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 usar el BeanFactory más liviano . Sin embargo, en la mayoría de las aplicaciones empresariales, el ApplicationContext es lo que querrá usar.

Para más información, vea mi publicación de blog:

Diferencia entre BeanFactory y ApplicationContext en Spring: el blog de Java Spring desde lo básico


0

Necesito explicar el BeanFactory & ApplicationContext.

BeanFactory: BeanFactory es la interfaz raíz para acceder a SpringBean Container. Hay una vista básica del cliente de un contenedor de beans. Esa interfaz es implementada por la clase de objeto que contiene el número de definiciones de beans, y cada uno se identifica de forma única por el nombre de la cadena.
Dependiendo de la definición de Bean, la fábrica devolverá la instancia que puede ser la instancia del objeto contenido o una única instancia compartida. El tipo de instancia que se devolverá depende de la configuración de fábrica de beans.
Normalmente, Bean factory cargará toda la definición de todos los beans, que se almacenan en la fuente de configuración como XML ... etc.

BeanFactory es un contenedor más simple que proporciona el soporte básico para la inyección de dependencia

Contexto de aplicación aplicación El contexto de la aplicación es una interfaz central con la aplicación de primavera que proporciona la información de configuración a la aplicación. Implementa la interfaz de Bean Factory.

El contexto de la aplicación es un contenedor avanzado, su nivel avanzado adicional de funcionalidad específica de la empresa, como la capacidad de resolver el mensaje de texto del archivo de propiedades ... etc.

Un ApplicationContext proporciona:

Métodos de fábrica de frijoles para acceder a los componentes de la aplicación. Heredado de ListableBeanFactory. La capacidad de cargar recursos de archivos de manera genérica. Heredado de la interfaz ResourceLoader. La capacidad de publicar eventos para oyentes registrados. Heredado de la interfaz ApplicationEventPublisher. La capacidad de resolver mensajes, apoyando la internacionalización. Heredado de la interfaz MessageSource. Herencia de un contexto padre. Las definiciones en un contexto descendiente siempre tendrán prioridad. Esto significa, por ejemplo, que una aplicación web completa puede usar un contexto padre único, mientras que cada servlet tiene su propio contexto hijo que es independiente del de cualquier otro servlet. Además de las capacidades estándar del ciclo de vida de BeanFactory,

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.