BeanFactory vs ApplicationContext

Sono abbastanza nuovo per il Framework di spring, ho giocato con esso e ho messo insieme alcune app di campioni allo scopo di valutare Spring MVC da utilizzare in un prossimo progetto aziendale. Finora mi piace molto quello che vedo in Spring MVC, sembra molto facile da usare e ti incoraggia a scrivere classi che sono molto facili da testare.

Proprio come esercizio, sto scrivendo un metodo principale per uno dei miei progetti di prova / campione. Una cosa che non mi è chiara sono le differenze esatte tra BeanFactory e ApplicationContext , che è appropriato usare in quali condizioni?

Capisco che ApplicationContext estende BeanFactory , ma se sto solo scrivendo un semplice metodo main, ho bisogno delle funzionalità extra fornite da ApplicationContext ? E proprio esattamente che tipo di funzionalità extra fornisce ApplicationContext ?

Oltre a rispondere “che dovrei usare in un metodo main ()”, esistono standard o linee guida per quanto riguarda l’implementazione che dovrei usare in tale scenario? Il mio metodo main () deve essere scritto in modo che dipenda dalla configurazione del bean / applicazione in formato XML? È un’ipotesi attendibile o sto bloccando l’utente in qualcosa di specifico?

E questa risposta cambia in un ambiente web – se qualcuno dei miei corsi dovesse essere a conoscenza di Spring, è più probabile che abbia bisogno di ApplicationContext ?

Grazie per qualsiasi aiuto. So che molte di queste domande sono probabilmente risposte nel manuale di riferimento, ma ho difficoltà a trovare una chiara ripartizione di queste due interfacce e dei pro / contro di ciascuno senza leggere il manuale con un pettine a denti stretti.

I documenti di spring sono grandi su questo: 3.8.1. BeanFactory o ApplicationContext? . Hanno una tabella con un confronto, pubblicherò uno snippet:

Fabbrica di fagioli

  • Istanziazione / cablaggio di fagioli

Contesto dell’applicazione

  • Istanziazione / cablaggio di fagioli
  • Registrazione automatica BeanPostProcessor
  • Registrazione automatica BeanFactoryPostProcessor
  • Comodo accesso a MessageSource (per i18n)
  • Pubblicazione ApplicationEvent

Quindi, se hai bisogno di uno qualsiasi dei punti presentati sul lato del contesto dell’applicazione, dovresti usare ApplicationContext.

Per me, la differenza principale tra cui scegliere BeanFactory su ApplicationContext sembra essere che ApplicationContext pre-istanzia tutti i bean. Dai documenti di spring :

Spring imposta le proprietà e risolve le dipendenze il più tardi ansible, quando il bean viene effettivamente creato. Ciò significa che un contenitore Spring che è stato caricato correttamente può in seguito generare un’eccezione quando si richiede un object in caso di problemi nel creare quell’object o una delle sue dipendenze. Ad esempio, il bean genera un’eccezione a causa di una proprietà mancante o non valida. Questa visibilità potenzialmente ritardata di alcuni problemi di configurazione è il motivo per cui le implementazioni ApplicationContext predefiniscono pre-istanza i bean singleton. Al costo di alcuni tempi iniziali e di memoria per creare questi bean prima che siano effettivamente necessari, si scoprono problemi di configurazione quando ApplicationContext viene creato, non più tardi. È comunque ansible sovrascrivere questo comportamento predefinito in modo che i bean singleton si inizializzino in modo pigro, anziché essere preistenziati.

BeanFactory questo, inizialmente ho scelto BeanFactory per l’utilizzo nei test di integrazione / prestazioni poiché non volevo caricare l’intera applicazione per testare i fagioli isolati. Tuttavia, e qualcuno mi corregge se ho torto: BeanFactory non supporta la configurazione XML del classpath . Quindi BeanFactory e ApplicationContext forniscono ciascuna una caratteristica cruciale che volevo, ma nessuno dei due ha mai fatto entrambe le cose.

Vicino a quanto posso dire, la nota nella documentazione sulla sovrascrittura del comportamento di istanza predefinito ha luogo nella configurazione, ed è per-bean, quindi non posso semplicemente impostare l’attributo “lazy-init” nel file XML o I’m bloccato mantenendo una versione di esso per il test e uno per la distribuzione.

Quello che ho finito è stato estendere ClassPathXmlApplicationContext per caricare pigramente i bean da usare in test come:

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

Per aggiungere quello che ha risposto Miguel Ping, ecco un’altra sezione della documentazione che risponde anche a questo:

Versione breve: usa un ApplicationContext a meno che tu non abbia una buona ragione per non farlo. Per quelli di voi che stanno cercando un po ‘più di profondità sul “ma perché” della raccomandazione di cui sopra, continuate a leggere.

(postando questo per eventuali futuri novizi di spring che potrebbero leggere questa domanda)

Spring fornisce due tipi di contenitori IOC, uno è XMLBeanFactory e l’altro è 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 | +---------------------------------------+-----------------+--------------------------------+ 

inserisci la descrizione dell'immagine qui

  • FileSystemXmlApplicationContext Beans caricati attraverso il percorso completo.
  • ClassPathXmlApplicationContext Beans caricati tramite CLASSPATH
  • XMLWebApplicationContext e AnnotationConfigWebApplicationContext bean caricati tramite il contesto dell’applicazione Web.
  • AnnotationConfigApplicationContext Caricamento di bean Spring da una configurazione basata su annotazioni.

esempio:

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class); 
  • ApplicationContext è il contenitore inizializzato da ContextLoaderListener o ContextLoaderServlet definito in un web.xml e ContextLoaderPlugin definito in ContextLoaderPlugin struts-config.xml .
  1. ApplicationContext è il modo più preferito di BeanFactory

  2. Nelle nuove versioni Spring BeanFactory viene sostituito con ApplicationContext . Ma esiste ancora BeanFactory per la retrocompatibilità

  3. ApplicationContext extends BeanFactory e offre i seguenti vantaggi
    • supporta l’internazionalizzazione per i messaggi di testo
    • supporta la pubblicazione degli eventi per gli ascoltatori registrati
    • accesso alle risorse come URL e file

Penso che sia meglio usare sempre ApplicationContext, a meno che tu non sia in un ambiente mobile come già detto da qualcun altro. ApplicationContext ha più funzionalità e sicuramente vuoi usare PostProcessors come RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor e CommonAnnotationBeanPostProcessor, che ti aiuteranno a semplificare i tuoi file di configurazione di Spring, e puoi usare annotazioni come @Required, @PostConstruct, @Resource, ecc. .

Anche se non usi tutte le cose offerte da ApplicationContext, è meglio usarlo comunque, e poi se decidi di utilizzare alcune risorse come messaggi o post processor o l’altro schema per aggiungere consigli transazionali e simili, tu avrà già un ApplicationContext e non avrà bisogno di cambiare alcun codice.

Se stai scrivendo un’app standalone, carica ApplicationContext nel tuo metodo principale, utilizzando ClassPathXmlApplicationContext, e ottieni il bean principale e invoca il suo run () (o qualsiasi altro metodo) per avviare la tua app. Se si sta scrivendo un’app Web, utilizzare ContextLoaderListener in web.xml in modo da creare ApplicationContext e successivamente recuperarlo da ServletContext, indipendentemente dal fatto che si utilizzi JSP, JSF, JSTL, struts, Tapestry, ecc. .

Inoltre, ricorda che puoi usare più file di configurazione di Spring e puoi creare ApplicationContext elencando tutti i file nel costruttore (o elencandoli nel contesto-param per ContextLoaderListener), oppure puoi semplicemente caricare un file di configurazione principale che ha dichiarazioni di importazione. È ansible importare un file di configurazione Spring in un altro file di configurazione Spring utilizzando che è molto utile quando si crea a livello di codice ApplicationContext nel metodo main e si carica solo un file di configurazione Spring.

  • BeanFactory: non supporta l’iniezione di dipendenza basata sull’annotazione .
  • ApplicationContext: supporto Iniezione basato su annotazione. – @ Autowired, @PreDestroy
  • BeanFactory: non supporta
  • ApplicationContext: i contesti dell’applicazione possono pubblicare eventi per i bean registrati come listener
  • BeanFactory: non supporta il modo di accedere a Message Bundle (internazionalizzazione (I18N)
  • ApplicationContext: supporto per i messaggi di internazionalizzazione (I18N).
  • BeanFactory: non supporta.
  • ApplicationContext: supporta molti servizi aziendali quali accesso JNDI, integrazione EJB, servizi remoti.
  • BeanFactory: per impostazione predefinita il suo supporto è il caricamento lento
  • ApplicationContext: È di default il caricamento Aggresive.

ApplicationContext: carica i bean spring configurati nel file di configurazione di spring e gestisce il ciclo di vita del bean spring come e WHEN CONTAINER STARTS. Non attenderà fino a quando non viene chiamato getBean (“springbeanref”) .

BeanFactory Carica i bean a molla configurati nel file di configurazione di spring, gestisce il ciclo di vita del bean spring quando chiamiamo getBean (“springbeanref”) . Così quando chiamiamo getBean (“springbeanref”) al momento dell’inizio del ciclo di vita del bean spring .

Per la maggior parte, ApplicationContext è preferibile a meno che non sia necessario salvare risorse, come su un’applicazione mobile.

Non sono sicuro di dipendere dal formato XML, ma sono abbastanza sicuro che le implementazioni più comuni di ApplicationContext siano quelle XML come ClassPathXmlApplicationContext, XmlWebApplicationContext e FileSystemXmlApplicationContext. Quelli sono gli unici tre che abbia mai usato.

Se stai sviluppando un’applicazione web, è sicuro che dovrai usare XmlWebApplicationContext.

Se vuoi che i tuoi bean siano a conoscenza di Spring, puoi farli implementare BeanFactoryAware e / o ApplicationContextAware per questo, quindi puoi usare BeanFactory o ApplicationContext e scegliere quale interfaccia implementare.

BeanFactory e ApplicationContext sono entrambi modi per ottenere i fagioli dal tuo contenitore IOC primaverile, ma ci sono ancora alcune differenze.

BeanFactory è il contenitore vero e proprio che istanzia, configura e gestisce un numero di bean. Questi bean sono in genere collaborativi tra loro e quindi hanno dipendenze tra loro. Queste dipendenze si riflettono nei dati di configurazione utilizzati da BeanFactory.

BeanFactory e ApplicationContext sono entrambe interfacce Java e ApplicationContext estende BeanFactory. Entrambi sono la configurazione che utilizza i file di configurazione XML. In breve BeanFactory fornisce funzionalità di Inversion of control ( IoC ) e Dependency Injection ( DI ) di base mentre ApplicationContext fornisce funzionalità avanzate .

A BeanFactory è rappresentato dall’interfaccia ” org.springframework.beans.factory ” Dove BeanFactory, per il quale esistono più implementazioni.

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

DIFFERENZA

  1. BeanFactory istanzia un bean quando chiamate il metodo getBean () mentre ApplicationContext crea un’istanza del bean Singleton all’avvio del contenitore, Non attende il richiamo di getBean ().

  2. BeanFactory non fornisce supporto per l’internazionalizzazione, ma ApplicationContext fornisce supporto per esso.

  3. Un’altra differenza tra BeanFactory e ApplicationContext è la possibilità di pubblicare eventi sui bean registrati come listener.

  4. Una delle implementazioni più diffuse dell’interfaccia BeanFactory è XMLBeanFactory mentre una delle più diffuse implementazioni dell’interfaccia ApplicationContext è ClassPathXmlApplicationContext .

  5. Se si utilizza il cablaggio automatico e si utilizza BeanFactory di quanto è necessario registrare AutoWiredBeanPostProcessor utilizzando l’API che è ansible configurare in XML se si utilizza ApplicationContext . In sintesi BeanFactory è OK per l’utilizzo di test e non di produzione, ma ApplicationContext è più un’implementazione di contenitore di funzionalità e dovrebbe essere preferito su BeanFactory

  6. BeanFactory per impostazione predefinita supporta il caricamento Lazy e ApplicationContext per il supporto predefinito Caricamento aggresivo .

Matrice di caratteristiche di Bean Factory vs Contesto applicativo proveniente dai documenti di spring

inserisci la descrizione dell'immagine qui

Screenshot delle funzionalità di BeanFacotry e ApplicationContext

Le differenze tra BeanFactory e ApplicationContext sono le seguenti:

  1. BeanFactory utilizza l’inizializzazione pigra ma ApplicationContext utilizza l’inizializzazione ansiosa. In caso di BeanFactory, il bean viene creato quando si chiama il metodo getBeans (), ma il bean viene creato in anticipo in caso di ApplicationContext quando viene creato l’object ApplicationContext.
  2. BeanFactory fornisce esplicitamente un object risorsa usando la syntax, ma ApplicationContext crea e gestisce gli oggetti risorsa da solo.
  3. BeanFactory non supporta internatiolization ma ApplicationContext supporta l’internazionalizzazione.
  4. Con l’iniezione della dipendenza basata sull’annotazione BeanFactory non è supportata, ma l’ integrazione delle dipendenze basata sull’annotazione è supportata in ApplicationContext.

Utilizzando BeanFactory:

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

Utilizzando ApplicationContext:

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

Fondamentalmente possiamo creare oggetti contenitore a molla in due modi

  1. usando BeatFactory
  2. usando ApplicationContext

entrambe sono le interfacce

utilizzando le classi di implementazione possiamo creare oggetti per il contenitore spring

venendo alle differenze

BeanFactory

  1. Non supporta l’iniezione di dipendenza basata sull’annotazione.

  2. Non supporta I18N

  3. Di default il suo supporto è il caricamento lento

  4. non consente di configurare più file di configurazione.

ex: contesto BeanFactory = new XmlBeanFactory (new Resource (“applicationContext.xml”));

ApplicationContext

  1. Sostenere la dipendenza basata sull’annotazione [email protected], @PreDestroy

  2. Supporto I18N

  3. il suo supporto predefinito Aggresive loading.

  4. consente di configurare più file di configurazione.

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

un. Una differenza tra bean factory e contesto applicativo è che ex solo bean di istanza quando si chiama il metodo getBean () mentre ApplicationContext crea un’istanza del bean Singleton all’avvio del contenitore. Non attende che venga richiamato getBean.

b.

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

o

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

È ansible utilizzare uno o più file xml in base ai requisiti del progetto. Siccome sono qui, utilizzo due file xml, uno per i dettagli di configurazione per le classi di servizio altro per le classi dao. Qui ClassPathXmlApplicationContext è figlio di ApplicationContext.

c. BeanFactory Container è un contenitore di base, può solo creare oggetti e iniettare dipendenze. Ma non possiamo albind altri servizi come sicurezza, transazioni, messaggistica ecc. Per fornire tutti i servizi che dobbiamo utilizzare ApplicationContext Container.

d. BeanFactory non fornisce supporto per l’internazionalizzazione, ad esempio i18n, ma ApplicationContext fornisce supporto per esso.

e. BeanFactory Container non supporta la funzionalità di AutoScanning (Supporto Injection basato su annotazione di supporto), ma supporta ApplicationContext Container.

f. Contenitore Beanfactory non creerà un object bean fino al tempo richiesto. Significa che il contenitore Beanfactory carica pigramente i fagioli. Mentre ApplicationContext Container crea oggetti del bean Singleton solo al momento del caricamento. Significa che c’è un caricamento anticipato.

g. Il contenitore Beanfactory supporta solo due ambiti (singleton e prototipo) dei bean. Ma ApplicationContext Container supporta tutti gli scope.

  1. BeanFactory utilizza l’ approccio di inizializzazione pigro mentre ApplicationContext utilizza un approccio di inizializzazione entusiasmante . cioè BeanFactory crea un bean singleton solo quando viene richiesto da esso, ma ApplicationContext crea tutti i bean singleton al momento della sua inizializzazione.

  2. ApplicationContext crea e gestisce gli oggetti risorse autonomamente, mentre BeanFactory ha utilizzato in modo esplicito un object risorsa che utilizza la syntax:

     ClassPathResource resource = new ClassPathResource("beans.xml"); XmlBeanFactory factory = new XmlBeanFactory(resource); // Here resource object is provided explicitly 
  3. ApplicationContext supporta l’internazionalizzazione, ma BeanFactory no.

  4. Dipendenza basata sull’annotazione Injection non è supportata da BeanFactory mentre ApplicationContext supporta l’uso dell’annotazione @PreDestroy, @Autowired.

Segnala questo documento da 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?

Usa un ApplicationContext a meno che tu non abbia una buona ragione per non farlo.

Poiché ApplicationContext include tutte le funzionalità di BeanFactory, in genere viene consigliato su BeanFactory, ad eccezione di alcune situazioni, ad esempio in un’applet in cui il consumo di memoria potrebbe essere critico e alcuni kilobyte aggiuntivi potrebbero fare la differenza. Tuttavia, per la maggior parte delle tipiche applicazioni e sistemi aziendali, ApplicationContext è ciò che si desidera utilizzare. Spring 2.0 e versioni successive fanno un uso intensivo del punto di estensione BeanPostProcessor (per effettuare il proxy e così via). Se si utilizza solo un BeanFactory semplice, una buona quantità di supporto come transazioni e AOP non avrà effetto, almeno non senza alcuni passaggi aggiuntivi da parte dell’utente. Questa situazione potrebbe essere fonte di confusione perché non c’è niente di sbagliato nella configurazione.

Differenza tra BeanFactory e ApplicationContext:

Org.springframework.beans.factory.BeanFactory e le interfacce org.springframework.context.ApplicationContext agiscono come contenitori IoC. L’interfaccia ApplicationContext è costruita sopra all’interfaccia BeanFactory. Aggiunge alcune funzionalità extra rispetto a BeanFactory, come la semplice integrazione con AOP di Spring, la gestione delle risorse dei messaggi (per I18N), la propagazione degli eventi, il contesto specifico del livello dell’applicazione (ad esempio WebApplicationContext) per l’applicazione web. Quindi è meglio usare ApplicationContext di BeanFactory.

ApplicationContext è un grande fratello di BeanFactory e questo è tutto ciò che BeanFactory fornisce oltre a molte altre cose.

Oltre alle funzionalità standard del ciclo di vita org.springframework.beans.factory.BeanFactory, le implementazioni ApplicationContext rilevano e richiamano i bean ApplicationContextAware nonché i bean ResourceLoaderAware, ApplicationEventPublisherAware e MessageSourceAware.

In uno scenario in tempo reale, la differenza tra il contenitore Spring IOC Core (BeanFactory) e Advanced J2EE (ApplicationContext) è la seguente.

  1. BeanFactory creerà oggetti per i bean (cioè, per le classi POJO) menzionati nel file spring.xml ( ) solo quando si chiama il metodo .getBean (), mentre ApplicationContext crea gli oggetti per tutti bean ( se il suo ambito non è esplicitamente menzionato come “Prototype”) configurato nel file spring.xml durante il caricamento del file spring.xml stesso.

  2. BeanFactory: (Contenitore pigro perché crea gli oggetti per i bean solo quando chiami esplicitamente dall’utente / class 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: (Eager contenitore a causa della creazione degli oggetti di tutti i bean singleton durante il caricamento del file spring.xml stesso)

     ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml"); 
  3. Tecnicamente, l’uso di ApplicationContext è consigliato perché nelle applicazioni in tempo reale, gli oggetti bean verranno creati mentre l’applicazione viene avviata nel server stesso. Ciò riduce il tempo di risposta per la richiesta dell’utente poiché gli oggetti sono già disponibili per rispondere.

Penso che valga la pena ricordare che dalla spring 3, se vuoi creare una fabbrica, puoi anche usare l’annotazione @configuration combinata con l’ @scope corretto

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

La tua fabbrica dovrebbe essere visibile dal contenitore Spring usando l’annotazione @ComponentScan o la configurazione xml

Articolo sugli ambiti dei bean di spring dal sito Baeldung

utilizzare BeanFactory per applicazioni non Web perché supporta solo ambiti di ambito Singleton e Prototype.

Mentre il contenitore ApplicationContext supporta tutti gli ambiti dei bean, dovresti usarlo per le applicazioni web.

In sintesi:

ApplicationContext include tutte le funzionalità di BeanFactory. In genere si consiglia di utilizzare il primo.

Ci sono alcune situazioni limitate come in un’applicazione mobile, in cui il consumo di memoria potrebbe essere critico.

In tali scenari, può essere giustificato utilizzare il più leggero BeanFactory . Tuttavia, nella maggior parte delle applicazioni aziendali, ApplicationContext è ciò che si desidera utilizzare.

Di più:

Differenza tra BeanFactory e ApplicationContext in spring – Il blog java spring dalle basi