web-dev-qa-db-fra.com

BeanFactory vs ApplicationContext

Je suis assez nouveau dans Spring Framework. Je me suis amusé avec lui et ai rassemblé quelques exemples d'applications afin d'évaluer Spring MVC en vue de son utilisation dans un projet d'entreprise à venir. Jusqu'ici, j'aime beaucoup ce que je vois dans Spring MVC, cela semble très facile à utiliser et vous encourage à écrire des cours très conviviaux pour les tests.

Juste comme exercice, j'écris une méthode principale pour l'un de mes échantillons/projets de test. Une chose que je ne comprends pas bien, ce sont les différences exactes entre BeanFactory et ApplicationContext - lequel convient-il d'utiliser dans quelles conditions?

Je comprends que ApplicationContext étend BeanFactory, mais si je viens d’écrire une méthode principale simple, ai-je besoin des fonctionnalités supplémentaires fournies par ApplicationContext? Et exactement quel type de fonctionnalité supplémentaire ApplicationContext fournit-il?

En plus de répondre "que dois-je utiliser dans une méthode main ()", existe-t-il des normes ou des directives concernant la mise en oeuvre à utiliser dans un tel scénario? Est-ce que ma méthode main () doit être écrite pour dépendre de la configuration du bean/application pour être au format XML - est-ce une hypothèse sûre, ou est-ce que je verrouille l'utilisateur dans quelque chose de spécifique?

Et cette réponse change-t-elle dans un environnement Web? Si certaines de mes classes devaient connaître Spring, auraient-elles plus besoin de ApplicationContext?

Merci pour toute aide. Je sais qu'un grand nombre de ces questions trouvent probablement une réponse dans le manuel de référence, mais j'ai du mal à trouver une ventilation claire de ces deux interfaces et des avantages/inconvénients de chacune d'entre elles sans avoir lu le manuel avec un peigne fin.

218
matt b

Les documents printaniers sont excellents à ce sujet: .8.1. BeanFactory ou ApplicationContext? . Ils ont un tableau avec une comparaison, je vais poster un extrait:

Usine de haricots

  • Instanciation/câblage des haricots

Contexte d'application

  • Instanciation/câblage des haricots
  • Enregistrement automatique de BeanPostProcessor
  • Enregistrement automatique de BeanFactoryPostProcessor
  • Accès pratique à MessageSource (pour i18n)
  • Publication ApplicationEvent

Donc, si vous avez besoin de l'un des points présentés du côté du contexte d'application, vous devez utiliser ApplicationContext.

200
Miguel Ping

Pour moi, la principale différence pour choisir BeanFactory par rapport à ApplicationContext semble être que ApplicationContext va pré-instancier tous les haricots. De les documents Spring :

Spring définit les propriétés et résout les dépendances aussi tard que possible, lorsque le bean est réellement créé. Cela signifie qu'un conteneur Spring chargé correctement peut générer ultérieurement une exception lorsque vous demandez un objet en cas de problème lors de la création de cet objet ou de l'une de ses dépendances. Par exemple, le bean lève une exception à la suite d'une propriété manquante ou non valide. Cette visibilité potentiellement retardée de certains problèmes de configuration explique pourquoi les implémentations d'ApplicationContext pré-instancient par défaut des beans singleton. Au prix d'un peu de temps et de mémoire pour créer ces beans avant qu'ils ne soient réellement utilisés, vous découvrez les problèmes de configuration lors de la création d'ApplicationContext, pas plus tard. Vous pouvez toujours remplacer ce comportement par défaut pour que les beans singleton s'initialisent paresseux plutôt que d'être pré-instanciés.

Cela étant dit, j’ai initialement choisi BeanFactory pour les tests d’intégration/de performance, car je ne souhaitais pas charger l’application complète pour tester les beans isolés. Cependant - et quelqu'un me corrige si je me trompe - BeanFactory ne prend pas en charge la configuration classpath XML. Ainsi, BeanFactory et ApplicationContext fournissent chacun une fonctionnalité cruciale que je voulais, mais les deux non plus.

Presque comme je peux le dire, la note dans la documentation sur le remplacement du comportement d’instanciation par défaut a lieu dans la configuration, et elle est par bean, je ne peux donc pas simplement définir l’attribut "lazy-init" dans le fichier XML. bloqué en maintenant une version pour le test et une pour le déploiement.

Ce que j'ai fini par faire était d'étendre ClassPathXmlApplicationContext pour charger paresseusement des haricots pour les utiliser dans des tests comme celui-ci:

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);
        }
    }

}
46
Lyle

Spring fournit deux types de conteneurs IOC, l'un est XMLBeanFactory et l'autre 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 chargés dans le chemin complet.
  • ClassPathXmlApplicationContext Beans chargés via le CLASSPATH
  • XMLWebApplicationContext et AnnotationConfigWebApplicationContext beans chargés via le contexte de l'application Web.
  • AnnotationConfigApplicationContext Chargement de beans Spring à partir d'une configuration basée sur des annotations.

exemple:

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ApplicationContext est le conteneur initialisé par un ContextLoaderListener ou ContextLoaderServlet défini dans un web.xml et ContextLoaderPlugin défini dans struts-config.xml.

Remarque : XmlBeanFactory est obsolète à compter du printemps 3.1 en faveur de DefaultListableBeanFactory et XmlBeanDefinitionReader.

41
Premraj

Pour ajouter à ce que Miguel Ping a répondu, voici ne autre section de la documentation qui répond également à cette question:

Version courte: utilisez un ApplicationContext sauf si vous avez une très bonne raison de ne pas le faire. Pour ceux d'entre vous qui recherchent un peu plus de profondeur quant au "mais pourquoi" de la recommandation ci-dessus, continuez à lire.

(en affichant ceci pour tous les futurs novices du printemps qui pourraient lire cette question)

29
matt b
  1. ApplicationContext est un moyen plus préféré que BeanFactory

  2. Dans les nouvelles versions de Spring, BeanFactory est remplacé par ApplicationContext. Mais toujours BeanFactory existe pour la compatibilité descendante

  3. ApplicationContext extends BeanFactory et présente les avantages suivants
    • il prend en charge l'internationalisation des messages texte
    • il prend en charge la publication d'événement pour les auditeurs inscrits
    • accès aux ressources telles que les URL et les fichiers
18
srinivas reddy

Je pense qu'il est préférable de toujours utiliser ApplicationContext, sauf si vous êtes dans un environnement mobile, comme quelqu'un l'a déjà dit. ApplicationContext a davantage de fonctionnalités et vous souhaitez absolument utiliser des post-processeurs tels que RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor et CommonAnnotationBeanPostProcessor, qui vous aideront à simplifier vos fichiers de configuration Spring et à utiliser des annotations telles que @Required, @PesConstruct, @Resources .

Même si vous n'utilisez pas tout le contenu offert par ApplicationContext, il est préférable de l'utiliser quand même, puis si vous décidez d'utiliser des ressources telles que des messages ou des post-processeurs, ou l'autre schéma pour ajouter des conseils transactionnels, etc. aura déjà un ApplicationContext et n'aura pas besoin de changer de code.

Si vous écrivez une application autonome, chargez le ApplicationContext dans votre méthode principale à l'aide d'un ClassPathXmlApplicationContext, récupérez le bean principal et appelez sa méthode run () (ou une méthode quelconque) pour démarrer votre application. Si vous écrivez une application Web, utilisez le ContextLoaderListener dans le fichier web.xml pour créer le ApplicationContext et le récupérer ultérieurement à partir du ServletContext, que vous utilisiez JSP, JSF, JSTL, struts, Tapestry, etc. .

En outre, rappelez-vous que vous pouvez utiliser plusieurs fichiers de configuration Spring et créer soit le ApplicationContext en listant tous les fichiers du constructeur (soit en les répertoriant dans le context-param du ContextLoaderListener), ou vous pouvez simplement charger un fichier de configuration principal contenant déclarations d'importation. Vous pouvez importer un fichier de configuration Spring dans un autre fichier de configuration Spring en utilisant <import resource = "otherfile.xml" />, ce qui est très utile lorsque vous créez par programme le ApplicationContext dans la méthode principale et que vous ne chargez qu'un seul fichier de configuration Spring.

12
Chochos

ApplicationContext: Il charge les haricots de printemps configurés dans le fichier de configuration de printemps et gère le cycle de vie du haricot de printemps au fur et à mesure QUE LE CONTENEUR COMMENCE. Il n'attendra pas getBean ("springbeanref") est appelé.

BeanFactory Il charge les haricots de printemps configurés dans le fichier de configuration de printemps, gère le cycle de vie du haricot de printemps lorsque nous appelons le getBean ("springbeanref"). Donc, lorsque nous appelons le - getBean ("springbeanref") au début du cycle de vie du haricot de printemps.

10
vinod

Dans la plupart des cas, ApplicationContext est préférable, sauf si vous devez économiser des ressources, comme dans une application mobile.

Je ne suis pas sûr de dépendre du format XML, mais je suis presque sûr que les implémentations les plus courantes d'ApplicationContext sont celles XML, telles que ClassPathXmlApplicationContext, XmlWebApplicationContext et FileSystemXmlApplicationContext. Ce sont les trois seuls que j'ai jamais utilisés.

Si vous développez une application Web, il est sûr de dire que vous devez utiliser XmlWebApplicationContext.

Si vous souhaitez que vos beans soient au courant de Spring, vous pouvez leur demander d'implémenter BeanFactoryAware et/ou ApplicationContextAware à cette fin. Vous pouvez donc utiliser BeanFactory ou ApplicationContext et choisir l'interface à implémenter.

6
Ryan Thames

Les différences entre BeanFactory et ApplicationContext sont les suivantes:

  1. BeanFactory utilise une initialisation différée but ApplicationContext utilise une initialisation rapide. Dans le cas de BeanFactory, le bean est créé lorsque vous appelez la méthode getBeans (), mais il est créé à l'avance dans le cas de ApplicationContext lors de la création de l'objet ApplicationContext.
  2. BeanFactory fournit explicitement un objet ressource en utilisant la syntaxe but ApplicationContext crée et gère lui-même des objets ressource.
  3. BeanFactory ne supporte pas l'internationalisation mais ApplicationContext supporte l'internationalisation.
  4. Avec BeanFactory, l'injection de dépendance basée sur l'annotation n'est pas prise en charge mais L'injection de dépendance basée sur l'annotation est prise en charge dans ApplicationContext.

en utilisant BeanFactory:

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

tilisation de ApplicationContext:

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

5
Raman Gupta

BeanFactory et ApplicationContext sont tous deux des moyens d'obtenir des haricots de votre conteneur de printemps IOC mais il y a tout de même une différence.

BeanFactory est le conteneur actuel qui instancie, configure et gère un certain nombre de beans. Ces haricots collaborent généralement les uns avec les autres et ont donc des dépendances entre eux. Ces dépendances sont reflétées dans les données de configuration utilisées par BeanFactory.

BeanFactory et ApplicationContext sont tous deux Java interfaces et ApplicationContext étend BeanFactory. Les deux sont une configuration utilisant des fichiers de configuration XML. En bref, BeanFactory fournit l’inversion de base des fonctionnalités de contrôle (IoC) et d’Injection de dépendances (DI), tandis que ApplicationContext fournit les fonctionnalités avancées.

Un BeanFactory est représenté par l'interface "org.springframework.beans.factory" Où BeanFactory, pour lequel il existe plusieurs implémentations.

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

DIFFÉRENCE

  1. BeanFactory instancie le bean lorsque vous appelez la méthode getBean () lorsque ApplicationContext instancie le bean Singleton lorsque le conteneur est démarré. Il n'attend pas que getBean () soit appelé.

  2. BeanFactory ne fournit pas de support pour l'internationalisation mais ApplicationContext le supporte.

  3. Une autre différence entre BeanFactory et ApplicationContext est la possibilité de publier un événement sur des beans enregistrés en tant qu'écouteur.

  4. L'une des implémentations populaires de l'interface BeanFactory est XMLBeanFactory, tandis que l'une des implémentations populaires de l'interface ApplicationContext est ClassPathXmlApplicationContext.

  5. Si vous utilisez le câblage automatique et utilisez BeanFactory, vous devez vous enregistrer AutoWiredBeanPostProcessor à l'aide d'une API que vous pouvez configurer en XML si vous utilisez ApplicationContext. En résumé BeanFactory est acceptable pour les tests et pour une utilisation non productive, mais ApplicationContext est une implémentation de conteneur plus riche en fonctionnalités et devrait être privilégié par rapport à BeanFactory

  6. BeanFactory par défaut son support Lazy chargement et ApplicationContext par défaut support Aggresive chargement.

5
Divyesh Kanzariya

Feature Matrix de Bean Factory vs Contexte de l'application provenant de documents de printemps

enter image description here

Capture d'écran des fonctionnalités de BeanFacotry et ApplicationContext

4
Lucky

une. Une différence entre la fabrique de beans et le contexte de l'application réside dans le fait que la version précédente instancie uniquement le bean lorsque vous appelez la méthode getBean (), tandis que ApplicationContext instancie le bean Singleton au démarrage du conteneur. Il n'attend pas que la requête de getBean soit appelée.

b.

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

ou

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

Vous pouvez utiliser un ou plusieurs fichiers XML en fonction des exigences de votre projet. Étant donné que j’utilise ici deux fichiers XML, l’un pour les détails de configuration des classes de service, d’autres pour les classes de Dao. Ici, ClassPathXmlApplicationContext est l'enfant de ApplicationContext.

c. BeanFactory Container est un conteneur de base, il ne peut créer que des objets et injecter des dépendances. Mais nous ne pouvons pas attacher d’autres services tels que la sécurité, les transactions, la messagerie, etc. pour fournir tous les services nécessaires à l’utilisation de ApplicationContext Container.

ré. BeanFactory ne fournit pas de support pour l’internationalisation, c’est-à-dire i18n, mais ApplicationContext en assure le support.

e. BeanFactory Container ne prend pas en charge la fonctionnalité AutoScanning (Injection basée sur la prise en charge d'annotations de support), mais ApplicationContext Container prend en charge.

f. Beanfactory Container ne créera pas d'objet bean avant l'heure de la demande. Cela signifie que Beanfactory Container charge les haricots paresseusement. Alors que ApplicationContext Container crée uniquement des objets du bean Singleton au moment du chargement. Cela signifie qu'il y a un chargement précoce.

g. Beanfactory Container ne prend en charge que deux portées (singleton et prototype) des haricots. Mais ApplicationContext Container supporte toute la portée des beans.

3
rajvineet

Fondamentalement, nous pouvons créer un objet conteneur de ressort de deux manières

  1. en utilisant BeatFactory
  2. en utilisant ApplicationContext

les deux sont les interfaces

en utilisant des classes d'implémentation, nous pouvons créer un objet pour conteneur de printemps

venir aux différences

BeanFactory

  1. Ne prend pas en charge l'injection de dépendance basée sur les annotations.

  2. Ne supporte pas I18N

  3. Par défaut son support Lazy loading

  4. cela ne permet pas de configurer plusieurs fichiers de configuration.

ex: BeanFactory context = new XmlBeanFactory (new Resource ("applicationContext.xml"));

ApplicationContext

  1. Prise en charge de la dépendance basée sur les annotations Injection.-@Autowired, @PreDestroy

  2. Soutenir I18N

  3. sa prise en charge par défaut agressif chargement.

  4. cela permet de configurer plusieurs fichiers de configuration.

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

3

Dans un scénario en temps réel, la différence entre le conteneur Spring IOC Core (BeanFactory) et le conteneur Advanced J2EE (ApplicationContext) est la suivante.

  1. BeanFactory créera des objets pour les beans (c'est-à-dire pour les classes POJO) mentionnés dans le fichier spring.xml (<bean></bean>) uniquement lorsque vous appelez la méthode .getBean (), alors qu'ApplicationContext crée les objets pour tous les beans ( <bean></bean> si son étendue n'est pas explicitement mentionnée comme "Prototype") configurée dans le fichier spring.xml lors du chargement du fichier spring.xml lui-même.

  2. BeanFactory: (conteneur paresseux car il crée les objets pour les beans uniquement lorsque vous appelez explicitement à partir de la classe utilisateur/principale)

    /*
     * 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: (Conteneur désagréable à cause de la création des objets de tous les beans singleton lors du chargement du fichier spring.xml lui-même)

    ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
    
  3. Techniquement, l'utilisation d'ApplicationContext est recommandée car, dans les applications temps réel, les objets de bean seront créés lors du démarrage de l'application sur le serveur lui-même. Cela réduit le temps de réponse pour la demande de l'utilisateur, car les objets sont déjà disponibles pour répondre.

1
Karthik Pon

ApplicationContext est un grand frère de BeanFactory et cela apporterait tout ce que BeanFactory fournit et bien d’autres choses encore.

Outre les fonctionnalités de cycle de vie org.springframework.beans.factory.BeanFactory standard, les implémentations ApplicationContext détectent et appellent les beans ApplicationContextAware ainsi que les beans ResourceLoaderAware, ApplicationEventPublisherAware et MessageSourceAware.

1

Référez-vous à ce document 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 ou ApplicationContext?

Utilisez un ApplicationContext sauf si vous avez une bonne raison de ne pas le faire.

Etant donné que le contexte d'application inclut toutes les fonctionnalités de BeanFactory, il est généralement recommandé de ne pas utiliser BeanFactory, à l'exception de quelques situations telles que l'utilisation d'une applet dans laquelle la consommation de mémoire peut être critique et quelques kilo-octets supplémentaires peuvent faire la différence. Cependant, pour la plupart des applications et des systèmes d’entreprise, ApplicationContext est ce que vous voulez utiliser. Spring 2.0 et les versions ultérieures utilisent beaucoup le point d'extension BeanPostProcessor (pour effectuer un proxy, etc.). Si vous utilisez uniquement un BeanFactory ordinaire, une partie importante du support, telle que les transactions et les AOP, ne prendra pas effet, du moins pas sans quelques étapes supplémentaires de votre part. Cette situation peut prêter à confusion parce que rien n’est vraiment faux avec la configuration.

1
Vijayan Srinivasan

En résumé:

Le ApplicationContext inclut toutes les fonctionnalités de BeanFactory. Il est généralement recommandé d'utiliser l'ancien.

Il existe certaines situations limitées, comme dans une application mobile, où la consommation de mémoire peut être critique.

Dans ce scénario, il peut être justifié d'utiliser le plus léger BeanFactory . Toutefois, dans la plupart des applications d’entreprise, vous souhaitez utiliser le champ ApplicationContext .

Pour plus, voir mon blog:

Différence entre BeanFactory et ApplicationContext in Spring - Le blog printanier Java de base

0
Zoltán Raffai

utilisez BeanFactory pour des applications non Web car il ne prend en charge que les portées de beans Singleton et Prototype.

Alors que le conteneur ApplicationContext prend en charge toutes les portées de bean, vous devez donc l'utiliser pour les applications Web.

0
Arun Raaj

Je pense qu'il est utile de mentionner que depuis le printemps 3, si vous souhaitez créer une usine, vous pouvez également utiliser l'annotation @configuration combinée avec la bonne @scope

_@Configuration
public class MyFactory {

    @Bean
    @Scope("prototype")
    public MyClass create() {
        return new MyClass();
    }
}
_

Votre usine doit être visible par le conteneur Spring à l’aide de l’annotation @ComponentScan ou de la configuration xml.

article sur les haricots de printemps du site baeldung

0
Ronan Quillevere