Domanda

Sono abbastanza nuovo con Spring Framework, ci ho provato e ho messo insieme alcune app di esempio 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 un esercizio, sto scrivendo un metodo principale per uno dei miei progetti di esempio / test. Una cosa di cui non sono chiaro è l'esatta differenza tra BeanFactory e ApplicationContext - che è appropriato usare in quali condizioni?

Comprendo che <=> si estende <=>, ma se sto solo scrivendo un semplice metodo principale, ho bisogno delle funzionalità extra che <=> fornisce? E esattamente quale tipo di funzionalità extra fornisce <=>?

Oltre a rispondere " quale dovrei usare in un metodo main () " ;, ci sono standard o linee guida per quanto riguarda l'implementazione che dovrei usare in un tale scenario? Il mio metodo main () dovrebbe essere scritto per dipendere dal fatto che la configurazione del bean / dell'applicazione sia in formato XML - è un presupposto sicuro o sto bloccando l'utente in qualcosa di specifico?

E questa risposta cambia in un ambiente web - se qualcuno dei miei corsi ha bisogno di essere a conoscenza di Spring, è più probabile che abbiano bisogno di <=>?

Grazie per l'aiuto. So che molte di queste domande hanno probabilmente una risposta nel manuale di riferimento, ma ho difficoltà a trovare una chiara suddivisione di queste due interfacce e i pro / contro di ciascuna senza leggere il manuale con un pettine a denti fini.

È stato utile?

Soluzione

I documenti di primavera sono fantastici su questo: 3.8.1. BeanFactory o ApplicationContext? . Hanno una tabella con un confronto, posterò uno snippet:

Bean Factory

  • Istanza / cablaggio del bean

Contesto dell'applicazione

  • Istanza / cablaggio del bean
  • Registrazione automatica di BeanPostProcessor
  • Registrazione automatica BeanFactoryPostProcessor
  • Comodo accesso a MessageSource (per i18n)
  • Pubblicazione ApplicationEvent

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

Altri suggerimenti

Per me, la differenza principale tra cui scegliere BeanFactory rispetto a ApplicationContext sembra che classpath preveda un'istanza di tutti i bean. Da the Primavera documenti :

  

Spring imposta le proprietà e risolve le dipendenze il più tardi possibile, quando il bean viene effettivamente creato. Ciò significa che un contenitore Spring caricato correttamente può in seguito generare un'eccezione quando si richiede un oggetto in caso di problemi durante la creazione di quell'oggetto o di 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 di ApplicationContext per impostazione predefinita pre-istanza bean singleton. A scapito di un po 'di tempo e memoria iniziali per creare questi bean prima che siano effettivamente necessari, si scoprono problemi di configurazione quando viene creato ApplicationContext, non in seguito. Puoi comunque ignorare questo comportamento predefinito in modo che i bean singleton inizializzino lazy, anziché essere pre-istanziati.

Detto questo, inizialmente ho scelto ClassPathXmlApplicationContext per l'uso nei test di integrazione / prestazioni poiché non volevo caricare l'intera applicazione per testare bean isolati. Tuttavia - e qualcuno mi correggerà se sbaglio - <=> non supporta <=> la configurazione XML. Quindi <=> e <=> forniscono ciascuno una caratteristica cruciale che volevo, ma nessuno dei due.

Quasi come posso dire, la nota nella documentazione sulla sostituzione del comportamento di istanza predefinito ha luogo nella configurazione ed è per-bean, quindi non posso semplicemente impostare " lazy-init " attributo nel file XML o sono bloccato a mantenerne una versione per il test e una per la distribuzione.

Quello che ho finito per fare è stato l'estensione di <=> per caricare pigramente i bean da utilizzare in test come questi:

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 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 qui la descrizione dell'immagine

  • FileSystemXmlApplicationContext Fagioli caricati lungo il percorso completo.
  • ClassPathXmlApplicationContext Fagioli caricati attraverso il CLASSPATH
  • XMLWebApplicationContext e AnnotationConfigWebApplicationContext bean caricati nel contesto dell'applicazione Web.
  • AnnotationConfigApplicationContext Caricamento dei bean di primavera dalla configurazione basata su annotazioni.

Esempio:

  ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
  • ContextLoaderListener è il contenitore inizializzato da un ContextLoaderServlet o web.xml definito in un ContextLoaderPlugin e struts-config.xml definito in XmlBeanFactory.

Nota : DefaultListableBeanFactory è obsoleto a partire dalla primavera 3.1 a favore di XmlBeanDefinitionReader e <=>.

Per aggiungere una risposta a 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à riguardo al "ma perché" della raccomandazione di cui sopra, continuate a leggere.

(pubblicandolo per eventuali futuri novizi di primavera che potrebbero leggere questa domanda)

  1. ApplicationContext è il modo più preferito di BeanFactory

  2. Nelle nuove versioni di Spring ApplicationContext extends BeanFactory viene sostituito con <=>. Ma esiste ancora <=> per compatibilità con le versioni precedenti

  3. <=> e presenta i seguenti vantaggi
    • supporta l'internazionalizzazione per i messaggi di testo
    • supporta la pubblicazione di eventi agli 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, @Postes, @Postes, @P .

Anche se non usi tutte le cose offerte da ApplicationContext, è meglio usarle comunque, e successivamente se decidi di usare alcune risorse come messaggi o post processori o l'altro schema per aggiungere consigli transazionali e tale, avrai già un ApplicationContext e non dovrai cambiare alcun codice.

Se stai scrivendo un'app standalone, carica ApplicationContext nel tuo metodo principale, usando ClassPathXmlApplicationContext, ottieni il bean principale e invoca il suo run () (o qualunque metodo) per avviare l'app. Se stai scrivendo un'app Web, usa ContextLoaderListener in web.xml in modo che crei ApplicationContext e successivamente puoi ottenerlo da ServletContext, indipendentemente dal fatto che tu stia usando JSP, JSF, JSTL, struts, Tapestry, ecc. .

Inoltre, ricorda che puoi utilizzare più file di configurazione di Spring e puoi creare ApplicationContext elencando tutti i file nel costruttore (o elencandoli nel parametro di contesto per ContextLoaderListener), oppure puoi semplicemente caricare una configurazione principale file con dichiarazioni di importazione. Puoi importare un file di configurazione di Spring in un altro file di configurazione di Spring usando & Lt; import resource = & Quot; otherfile.xml & Quot; / Gt &; che è molto utile quando si crea a livello di codice ApplicationContext nel metodo principale e si carica un solo file di configurazione Spring.

ApplicationContext: Carica i bean di primavera configurati nel file di configurazione di primavera e gestisce il ciclo di vita del bean di primavera man mano che inizia IL CONTENITORE e non attende fino a getBean (& Quot; springbeanref & Quot;) .

BeanFactory  Carica i bean di primavera configurati nel file di configurazione di primavera, gestisce il ciclo di vita del bean di primavera quando chiamiamo getBean (& Quot; springbeanref & Quot;) .Quindi quando chiamiamo < strong> getBean (" springbeanref ") al momento dell'inizio del ciclo di vita del fagiolo primaverile.

Per la maggior parte, si preferisce ApplicationContext a meno che non sia necessario risparmiare 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 sono quelle XML come ClassPathXmlApplicationContext, XmlWebApplicationContext e FileSystemXmlApplicationContext. Questi sono gli unici tre che abbia mai usato.

Se stai sviluppando un'app Web, è sicuro dire che dovrai usare XmlWebApplicationContext.

Se vuoi che i tuoi fagioli siano a conoscenza di Spring, puoi farli implementare BeanFactoryAware e / o ApplicationContextAware per quello, 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 di primavera ma ci sono ancora delle differenze.

BeanFactory è il contenitore effettivo che crea un'istanza, configura e gestisce un numero di bean. Questi bean in genere collaborano tra loro e quindi hanno dipendenze tra di loro. Queste dipendenze si riflettono nei dati di configurazione utilizzati da BeanFactory.

BeanFactory e ApplicationContext sono entrambi interfacce Java e ApplicationContext estende BeanFactory. Entrambi sono configurati usando file di configurazione XML. In breve, BeanFactory fornisce le funzioni base di Inversione del controllo ( IoC ) e Iniezione delle dipendenze ( DI ) mentre ApplicationContext fornisce funzioni avanzate .

Una BeanFactory è rappresentata dall'interfaccia " org.springframework.beans.factory " Dove BeanFactory, per il quale esistono molteplici implementazioni.

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

DIFFERENZA

  1. BeanFactory istanza bean quando si chiama il metodo getBean () mentre ApplicationContext crea un'istanza bean Singleton all'avvio del contenitore, non attende che getBean () essere chiamato.

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

  3. Un'altra differenza tra BeanFactory vs ApplicationContext è la possibilità di pubblicare eventi su bean registrati come listener.

  4. Una delle implementazioni popolari dell'interfaccia BeanFactory è XMLBeanFactory mentre una delle implementazioni popolari dell'interfaccia ApplicationContext è ClassPathXmlApplicationContext .

  5. Se si utilizza il cablaggio automatico e si utilizza BeanFactory di quanto sia necessario registrare AutoWiredBeanPostProcessor utilizzando l'API che è possibile configurare in XML se si utilizza ApplicationContext . In breve BeanFactory è OK per i test e l'uso non di produzione, ma ApplicationContext è un'implementazione del contenitore più ricca di funzionalità e dovrebbe essere favorita rispetto a BeanFactory

  6. BeanFactory per impostazione predefinita supporta Lazy caricamento e ApplicationContext per supporto predefinito Aggresive . / p>

Le differenze tra BeanFactory e ApplicationContext sono le seguenti:

  1. BeanFactory utilizza l'inizializzazione lenta ma ApplicationContext utilizza l'inizializzazione desiderosa. Nel caso di BeanFactory, il bean viene creato quando si chiama il metodo getBeans (), ma il bean viene creato in anticipo nel caso di ApplicationContext quando viene creato l'oggetto ApplicationContext.
  2. BeanFactory fornisce esplicitamente un oggetto risorsa usando la sintassi ma ApplicationContext crea e gestisce gli oggetti risorsa da solo.
  3. BeanFactory non supporta l'internazionalizzazione ma ApplicationContext supporta l'internazionalizzazione.
  4. Con BeanFactory l'iniezione delle dipendenze basata su annotazioni non è supportata ma l'iniezione delle dipendenze basata su annotazioni è supportata in ApplicationContext.

Uso di BeanFactory:

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

Utilizzo di ApplicationContext:

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

Matrice delle funzionalità di Bean Factory vs contesto dell'applicazione proveniente da documenti di primavera

 inserisci qui la descrizione dell'immagine

Schermata delle funzionalità di BeanFacotry e ApplicationContext

Fondamentalmente possiamo creare un oggetto contenitore primavera in due modi

  1. usando BeatFactory
  2. utilizzando ApplicationContext

entrambe sono le interfacce

usando le classi di implementazione possiamo creare oggetti per il contenitore di primavera

venendo alle differenze

BeanFactory

  1. Non supporta l'iniezione di dipendenza basata su annotazioni.

  2. Non supporta I18N

  3. Di default supporta il caricamento lento

  4. non consente la configurazione su più file di configurazione.

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

ApplicationContext

  1. Supporta dipendenza basata su annotazioni Iniezione.-@Autowired, @PreDestroy

  2. Supporto I18N

  3. supporto predefinito Caricamento aggressivo.

  4. consente di configurare più file di configurazione.

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

a. Una differenza tra la fabbrica di bean e il contesto dell'applicazione è che il precedente ha solo un'istanza del bean quando si chiama il metodo getBean () mentre ApplicationContext crea un'istanza del bean Singleton all'avvio del contenitore, non attende la chiamata di getBean.

b.

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

o

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

È possibile utilizzare uno o più file XML a seconda delle esigenze del progetto. Dato che sto usando due file XML, ovvero uno per i dettagli di configurazione per le classi di servizio, altre per le classi dao. Qui ClassPathXmlApplicationContext è figlio di ApplicationContext.

c. Il contenitore BeanFactory è un contenitore di base, può solo creare oggetti e iniettare dipendenze. Ma non possiamo & # 8217; t allegare altri servizi come sicurezza, transazioni, messaggistica ecc. Per fornire tutti i servizi che dobbiamo usare ApplicationContext Container.

d. BeanFactory non fornisce supporto per l'internazionalizzazione, cioè i18n, ma ApplicationContext fornisce supporto per esso.

e. BeanFactory Container non supporta la funzione di AutoScanning (Iniezione di dipendenza basata su annotazioni di supporto), ma supporta il contenitore ApplicationContext.

f. Beanfactory Container non creerà un oggetto bean fino al momento della richiesta. Significa che Beanfactory Container carica pigramente i fagioli. Mentre ApplicationContext Container crea oggetti del bean Singleton solo al momento del caricamento. Significa che c'è un caricamento anticipato.

g. Beanfactory Container supporta solo due ambiti (singleton & Amp; prototype) dei bean. Ma ApplicationContext Container supporta tutto l'ambito dei bean.

Consulta 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, è generalmente consigliato rispetto a BeanFactory, ad eccezione di alcune situazioni come in un applet in cui il consumo di memoria potrebbe essere critico e alcuni kilobyte in più potrebbero fare la differenza. Tuttavia, per le applicazioni e i sistemi aziendali più tipici, ApplicationContext è ciò che si desidera utilizzare. Spring 2.0 e successive fanno un uso intensivo del punto di estensione BeanPostProcessor (per effettuare il proxy e così via). Se si utilizza solo una semplice BeanFactory, una buona quantità di supporto come transazioni e AOP non avrà effetto, almeno non senza alcuni passaggi aggiuntivi da parte tua. Questa situazione potrebbe essere fonte di confusione perché nulla è effettivamente sbagliato nella configurazione.

ApplicationContext è un fratello maggiore di BeanFactory e tutto ciò che BeanFactory fornirà, oltre a molte altre cose.

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

In uno scenario in tempo reale, le differenze tra il contenitore Spring IOC Core (BeanFactory) e il contenitore Advanced J2EE (ApplicationContext) sono le seguenti.

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

  2. BeanFactory: (contenitore pigro perché crea gli oggetti per i bean solo quando si chiama esplicitamente dall'utente / classe 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: (contenitore desideroso 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, si consiglia di utilizzare ApplicationContext perché nelle applicazioni in tempo reale, gli oggetti bean verranno creati mentre l'applicazione viene avviata nel server stesso. Ciò riduce i tempi di risposta per la richiesta dell'utente poiché gli oggetti sono già disponibili per rispondere.

Penso che valga la pena ricordare che dalla primavera 3, se si desidera creare una fabbrica, è possibile utilizzare anche @configuration combinato con la corretta @scope

@Configuration
public class MyFactory {

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

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

Articolo sugli ambiti dei bean di primavera dal sito baeldung

usa BeanFactory per applicazioni non web perché supporta solo gli ambiti bean Singleton e Prototype.

Mentre il contenitore ApplicationContext supporta tutti gli ambiti bean, è consigliabile utilizzarlo per le applicazioni Web.

In sintesi:

Il ApplicationContext include tutte le funzionalità di BeanFactory. Si consiglia generalmente di utilizzare il primo.

Esistono alcune situazioni limitate, ad esempio in un'applicazione mobile, in cui il consumo di memoria potrebbe essere critico.

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

Per ulteriori informazioni, vedi il mio post sul blog:

Differenza tra BeanFactory e ApplicationContext in primavera & # 8211 ; Il blog di java spring dalle basi

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top