Question

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 pour une 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.

À titre d’exercice, j’écris une méthode principale pour l’un de mes projets d’échantillon / test. Une chose que je ne comprends pas bien, ce sont les différences exactes entre BeanFactory et ApplicationContext - quelle est l’utilisation appropriée dans quelles conditions?

Je comprends que <=> s'étend <=>, mais si je viens d’écrire une méthode principale simple, ai-je besoin des fonctionnalités supplémentaires fournies par <=>? Et quel type de fonctionnalité supplémentaire <<> 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 œuvre à 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 de chances de le faire <=>?

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.

Était-ce utile?

La solution

Les documents printaniers sont excellents à cet égard: 3.8.1. BeanFactory ou ApplicationContext? . Ils ont un tableau avec une comparaison, je vais poster un extrait:

Bean Factory

  • Instanciation / câblage de haricots

Contexte d'application

  • Instanciation / câblage de 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é Contexte de l'application, vous devez utiliser ApplicationContext.

Autres conseils

Pour moi, la principale différence à choisir BeanFactory par rapport à ApplicationContext semble être que classpath va pré-instancier tous les beans. De the Printemps docs :

  

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 nécessaires, 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.

Dans ce contexte, j’avais initialement choisi ClassPathXmlApplicationContext 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 - <=> ne prend pas en charge la <=> configuration XML. Ainsi, <=> et <=> fournissent chacun une fonctionnalité cruciale que je voulais, mais les deux non plus.

Comme je peux le constater, la note de la documentation relative au remplacement du comportement d'instanciation par défaut se trouve dans la configuration, et c'est par bean, je ne peux donc pas définir le & "; lazy-init " attribut dans le fichier XML ou je suis bloqué en maintenant une version pour le test et une pour le déploiement.

Ce que j'ai fini par faire était d'étendre <=> pour charger paresseusement des beans à 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);
        }
    }

}
  

Spring fournit deux types de conteneurs IOC: l’un est XMLBeanFactory et l’autre est 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                            |
+---------------------------------------+-----------------+--------------------------------+

 entrez la description de l'image ici

  • FileSystemXmlApplicationContext Beans chargés via 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 des beans Spring à partir de la configuration basée sur les annotations.

exemple:

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

Remarque : DefaultListableBeanFactory est déconseillé à partir de Spring 3.1 en faveur de XmlBeanDefinitionReader et <=>.

Pour ajouter à ce à quoi Miguel Ping a répondu, voici une 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 publiant ceci pour les futurs novices du printemps susceptibles de lire cette question)

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

  2. Dans les nouvelles versions de Spring, ApplicationContext extends BeanFactory est remplacé par <=>. Mais il existe toujours <=> une compatibilité ascendante

  3. <=> 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 écouteurs enregistrés
    • accès aux ressources telles que les URL et les fichiers

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 tous les éléments proposés par ApplicationContext, il est préférable de les utiliser de toute façon, 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 et De ce fait, vous aurez déjà un ApplicationContext et vous ne devrez changer aucun 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 qu'il crée le ApplicationContext et que vous puissiez le récupérer ultérieurement à partir du ServletContext, que vous utilisiez JSP, JSF, JSTL, struts, Tapestry, etc. .

N'oubliez pas non plus que vous pouvez utiliser plusieurs fichiers de configuration Spring et vous pouvez créer le champ ApplicationContext en listant tous les fichiers du constructeur (ou en les listant dans le paramètre context pour le ContextLoaderListener), ou vous pouvez simplement charger une configuration principale. fichier qui a des déclarations d'importation. Vous pouvez importer un fichier de configuration Spring dans un autre fichier de configuration Spring à l'aide de & Lt; import resource = & Quot; otherfile.xml & Quot; / > ce qui est très utile lorsque vous créez par programme l'ApplicationContext dans la méthode principale et ne chargez qu'un seul fichier de configuration Spring.

Contexte d'application: 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 QUAND LE CONTENEUR COMMENCE. Il n'attendra pas getBean (& "; Springbeanref &"; s'appelle.

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 getBean (& "Springbeanref &";) .Alors, lorsque nous appelons < strong> getBean (& "; springbeanref &";) au début du cycle de vie du haricot de printemps.

Pour la plupart, ApplicationContext est préférable, sauf si vous devez économiser des ressources, comme sur 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, vous devrez sans doute utiliser XmlWebApplicationContext.

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

BeanFactory et ApplicationContext permettent d'obtenir des haricots de votre conteneur IOC , mais il y a tout de même une différence.

BeanFactory est le conteneur 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 deux interfaces Java 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épendance ( DI ), tandis que ApplicationContext fournit des fonctionnalités avancées .

Une BeanFactory est représentée 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);

DIFFERENCE

  1. BeanFactory instanciez un bean lorsque vous appelez la méthode getBean () pendant qu'ApplicationContext instancie un bean Singleton lorsque le conteneur est lancé. Il n'attend pas que getBean () être appelé.

  2. BeanFactory ne prend pas en charge l'internationalisation, mais ApplicationContext le prend en charge.

  3. Une autre différence entre BeanFactory et Contexte d'application est la possibilité de publier des événements sur des beans enregistrés en tant qu'écouteur.

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

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

  6. BeanFactory prend en charge par défaut le chargement paresseux et le ApplicationContext par défaut, le support Aggresive <.>.

La différence entre BeanFactory et ApplicationContext est la suivante:

  1. BeanFactory utilise une initialisation différée mais 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 mais ApplicationContext crée et gère lui-même des objets ressource.
  3. BeanFactory ne prend pas en charge l'internatiolisation mais ApplicationContext prend en charge l'internationalisation.
  4. L'injection de dépendance basée sur les annotations BeanFactory n'est pas prise en charge mais l'injection de dépendance basée sur les annotations est prise en charge dans ApplicationContext.

Utilisation de BeanFactory:

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

Utilisation de ApplicationContext:

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

Matrice de fonctionnalités de Bean Factory par rapport au contexte d'application provenant de la documentation de printemps

 entrer la description de l'image ici

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

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

  1. utilisant BeatFactory
  2. utilisant ApplicationContext

les deux sont les interfaces

En utilisant les classes d'implémentation, nous pouvons créer un objet pour le conteneur Spring

venir aux différences

BeanFactory

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

  2. Ne prend pas en charge I18N

  3. Par défaut sa prise en charge Chargement paresseux

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

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

Contexte d'application

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

  2. Prise en charge de l'I18N

  3. sa prise en charge par défaut de charge agressive.

  4. permet de configurer plusieurs fichiers de configuration.

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

a. Une différence entre la fabrique de beans et le contexte d’application réside dans le fait qu’il n’instancie le bean que lorsque vous appelez la méthode getBean () alors que ApplicationContext instancie le bean Singleton lors du démarrage du conteneur. Il n’attend pas l’appel de getBean.

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, c’est-à-dire l’un pour les détails de la 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 & # 8217; pas associer 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.

d. 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 beans. Mais ApplicationContext Container supporte toute la portée des beans.

Référez-vous à ce document depuis 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 contexte d'application 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, comme dans un applet, dans lesquelles la consommation de mémoire peut être critique et quelques kilo-octets supplémentaires peuvent faire une 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 font un usage intensif du 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.

ApplicationContext est un grand frère de BeanFactory et tout cela est fourni par BeanFactory 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  invoquez les beans ApplicationContextAware ainsi que les beans ResourceLoaderAware, ApplicationEventPublisherAware et MessageSourceAware.

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 (<=> si son étendue n'est pas explicitement mentionnée comme & "; prototype &";) configurés dans le fichier spring.xml lors du chargement du fichier spring.xml lui-même.

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

    /*
     * 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 du fait 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 bean seront créés pendant le 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.

Je pense qu'il vaut la peine de mentionner que depuis le printemps 3, si vous souhaitez créer une fabrique, vous pouvez également utiliser @configuration , associée à la bonne @scope

@Configuration
public class MyFactory {

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

Votre usine devrait être visible par le conteneur Spring à l'aide de @ComponentScan annotation ou configuration xml

article sur les haricots de printemps du site baeldung

utilise BeanFactory pour des applications non Web car il ne prend en charge que les scopes Singleton et Prototype.

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

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, dans lesquelles la consommation de mémoire peut être critique.

Dans ces scénarios, il peut être justifié d'utiliser le BeanFactory , plus léger. Cependant, dans la plupart des applications d'entreprise, vous souhaiterez utiliser ApplicationContext .

Pour plus d'informations, consultez mon article de blog:

Différence entre BeanFactory et ApplicationContext au printemps & # 8211 ; Le blog Java Spring des bases

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top