Ich bin ziemlich neu im Spring Framework, habe ein paar Beispiele für Apps zusammengestellt, um Spring MVC für ein bevorstehendes Unternehmensprojekt zu evaluieren. Bisher gefällt mir das, was ich in Spring MVC sehe, sehr gut und ich ermutige Sie, Klassen zu schreiben, die sehr Unit-Test-freundlich sind.
Nur als Übung schreibe ich eine Hauptmethode für eines meiner Beispiel-/Testprojekte. Eine Sache, über die ich unklar bin, sind die genauen Unterschiede zwischen BeanFactory
und ApplicationContext
- welche ist geeignet, um unter welchen Bedingungen verwendet zu werden?
Ich verstehe, dass ApplicationContext
BeanFactory
erweitert, aber wenn ich nur eine einfache Hauptmethode schreibe, benötige ich die zusätzliche Funktionalität, die ApplicationContext
bietet? Und genau welche zusätzlichen Funktionen bietet ApplicationContext
?
Gibt es neben der Antwort "Welche sollte ich in einer main () -Methode verwenden?" Noch Standards oder Richtlinien für die Implementierung in einem solchen Szenario? Sollte meine main () -Methode so geschrieben werden, dass sie von der Bean-/Anwendungskonfiguration im XML-Format abhängt - ist das eine sichere Annahme, oder sperre ich den Benutzer in etwas Bestimmtes ein?
Und ändert sich diese Antwort in einer Webumgebung - wenn eine meiner Klassen Spring berücksichtigen musste, ist es dann wahrscheinlicher, dass sie ApplicationContext
benötigen?
Vielen Dank für jede Hilfe. Ich weiß, dass viele dieser Fragen wahrscheinlich im Referenzhandbuch beantwortet werden, aber es fällt mir schwer, eine klare Aufschlüsselung dieser beiden Schnittstellen und ihrer Vor- und Nachteile zu finden, ohne das Handbuch mit einem feinen Kamm durchzulesen.
Die Frühlingsdokumente sind in dieser Hinsicht großartig: .8.1. BeanFactory oder ApplicationContext? . Sie haben eine Tabelle mit einem Vergleich, ich werde ein Snippet posten:
Bohnenfabrik
Anwendungskontext
Wenn Sie also einen der Punkte benötigen, die auf der Seite Anwendungskontext angezeigt werden, sollten Sie ApplicationContext verwenden.
Für mich scheint der Hauptunterschied bei der Auswahl von BeanFactory
gegenüber ApplicationContext
darin zu liegen, dass ApplicationContext
alle Beans vorinstanziert. Von den Spring docs :
Spring legt Eigenschaften fest und löst Abhängigkeiten so spät wie möglich auf, wenn die Bean tatsächlich erstellt wird. Dies bedeutet, dass ein ordnungsgemäß geladener Spring-Container später eine Ausnahme generieren kann, wenn Sie ein Objekt anfordern, wenn beim Erstellen dieses Objekts oder einer seiner Abhängigkeiten ein Problem auftritt. Beispielsweise löst die Bean eine Ausnahme aufgrund einer fehlenden oder ungültigen Eigenschaft aus. Diese möglicherweise verzögerte Sichtbarkeit einiger Konfigurationsprobleme ist der Grund, warum ApplicationContext-Implementierungen Singleton-Beans standardmäßig vorinstanziieren. Auf Grund der Zeit und des Arbeitsspeichers, die erforderlich sind, um diese Beans zu erstellen, stellen Sie Konfigurationsprobleme fest, wenn der ApplicationContext erstellt wird, und nicht später. Sie können dieses Standardverhalten weiterhin außer Kraft setzen, sodass Singleton-Beans nicht vorab instanziiert, sondern nur verzögert initialisiert werden.
Vor diesem Hintergrund habe ich BeanFactory
für die Verwendung in Integrations-/Leistungstests ausgewählt, da ich nicht die gesamte Anwendung zum Testen von isolierten Beans laden wollte. Allerdings - und jemand korrigiert mich, wenn ich falsch liege - unterstützt BeanFactory
keine classpath
XML-Konfiguration. Also bieten BeanFactory
und ApplicationContext
jeweils eine wichtige Funktion, die ich wollte, aber beides auch nicht.
Soweit ich das beurteilen kann, findet der Hinweis in der Dokumentation zum Überschreiben des Standard-Instanziierungsverhaltens in der Konfiguration statt und bezieht sich auf eine Bean. Ich kann also nicht einfach das Attribut "Lazy-Init" in der XML-Datei festlegen, oder ich bin steckengeblieben eine Version davon für Test und eine für die Bereitstellung.
Am Ende habe ich ClassPathXmlApplicationContext
erweitert, um Beans für Tests wie diesen zu laden:
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 bietet zwei Arten von IOC Container, einer ist
XMLBeanFactory
und der andere istApplicationContext
.
+---------------------------------------+-----------------+--------------------------------+
| | 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 |
+---------------------------------------+-----------------+--------------------------------+
FileSystemXmlApplicationContext
Beans werden über den gesamten Pfad geladen.ClassPathXmlApplicationContext
Beans, die durch den CLASSPATH geladen wurdenXMLWebApplicationContext
und AnnotationConfigWebApplicationContext
Beans, die über den Webanwendungskontext geladen werden.AnnotationConfigApplicationContext
Laden von Spring Beans aus einer Annotation-basierten Konfiguration.beispiel:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
ApplicationContext
ist der Container, der durch einen ContextLoaderListener
oder ContextLoaderServlet
initialisiert wird, der in einem web.xml
und ContextLoaderPlugin
definiert in struts-config.xml
. Hinweis : XmlBeanFactory
ist veraltet ab Frühjahr 3.1 zugunsten von DefaultListableBeanFactory
und XmlBeanDefinitionReader
.
Um das, was Miguel Ping beantwortet hat, zu ergänzen, ist hier ein weiterer Abschnitt aus der Dokumentation , der auch dies beantwortet:
Kurzversion: Verwenden Sie einen ApplicationContext, es sei denn, Sie haben einen guten Grund, dies nicht zu tun. Für diejenigen von Ihnen, die nach etwas mehr Tiefe als dem "Aber warum" der obigen Empfehlung suchen, lesen Sie weiter.
(Posten Sie dies für alle zukünftigen Spring-Neulinge, die diese Frage lesen könnten.)
ApplicationContext
ist bevorzugter als BeanFactory
In neuen Spring-Versionen wird BeanFactory
durch ApplicationContext
ersetzt. Aus Gründen der Rückwärtskompatibilität ist BeanFactory
jedoch noch vorhanden
ApplicationContext extends BeanFactory
und hat folgende Vorteile Ich denke, es ist besser, immer ApplicationContext zu verwenden, es sei denn, Sie befinden sich in einer mobilen Umgebung, wie bereits jemand anderes gesagt hat. ApplicationContext bietet mehr Funktionen, und Sie möchten auf jeden Fall die PostProcessors wie RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor und CommonAnnotationBeanPostProcessor verwenden, um Ihre Spring-Konfigurationsdateien zu vereinfachen. Außerdem können Sie Anmerkungen wie @Required, @PostConstruct usw. verwenden .
Auch wenn Sie nicht alle von ApplicationContext angebotenen Informationen verwenden, ist es besser, sie trotzdem zu verwenden, und später, wenn Sie sich dazu entschließen, Ressourcen wie Nachrichten oder Postprozessoren oder das andere Schema zum Hinzufügen von Transaktionshinweisen und dergleichen zu verwenden verfügt bereits über einen ApplicationContext und muss keinen Code ändern.
Wenn Sie eine eigenständige App schreiben, laden Sie den ApplicationContext mithilfe eines ClassPathXmlApplicationContext in Ihre Hauptmethode, rufen Sie die Haupt-Bean auf und rufen Sie run () (oder eine andere Methode) auf, um Ihre App zu starten. Wenn Sie eine Webanwendung schreiben, verwenden Sie den ContextLoaderListener in web.xml, damit er den ApplicationContext erstellt und Sie ihn später vom ServletContext abrufen können, unabhängig davon, ob Sie JSP, JSF, JSTL, Struts, Tapestry usw. Verwenden .
Denken Sie auch daran, dass Sie mehrere Spring-Konfigurationsdateien verwenden und entweder den ApplicationContext erstellen können, indem Sie alle Dateien im Konstruktor auflisten (oder sie im Kontextparameter für den ContextLoaderListener auflisten), oder Sie können einfach eine Hauptkonfigurationsdatei laden, die über Folgendes verfügt Anweisungen importieren. Sie können eine Spring-Konfigurationsdatei mithilfe von <import resource = "otherfile.xml" /> in eine andere Spring-Konfigurationsdatei importieren. Dies ist sehr nützlich, wenn Sie den ApplicationContext in der Hauptmethode programmgesteuert erstellen und nur eine Spring-Konfigurationsdatei laden.
ApplicationContext: Lädt in der Spring-Konfigurationsdatei konfigurierte Spring-Beans und verwaltet den Lebenszyklus der Spring-Beans als und WENN CONTAINER STARTET. Es wird nicht warten bis getBean ("springbeanref") heißt.
BeanFactory Lädt in der Spring-Konfigurationsdatei konfigurierte Spring-Beans und verwaltet den Lebenszyklus der Spring-Beans, wenn wir getBean ("springbeanref") aufrufen. Wenn wir also - aufrufen getBean ("springbeanref") zum Zeitpunkt des Starts des Lebenszyklus der Bohne.
In den meisten Fällen wird ApplicationContext bevorzugt, es sei denn, Sie müssen Ressourcen wie bei einer mobilen Anwendung sparen.
Abhängig vom XML-Format bin ich mir nicht sicher, aber ich bin mir ziemlich sicher, dass die gängigsten Implementierungen von ApplicationContext XML-Implementierungen wie ClassPathXmlApplicationContext, XmlWebApplicationContext und FileSystemXmlApplicationContext sind. Das sind die einzigen drei, die ich jemals benutzt habe.
Wenn Sie eine Web-App entwickeln, müssen Sie mit Sicherheit XmlWebApplicationContext verwenden.
Wenn Sie möchten, dass Ihre Beans Spring kennen, können Sie dafür BeanFactoryAware und/oder ApplicationContextAware implementieren. Sie können also entweder BeanFactory oder ApplicationContext verwenden und die zu implementierende Schnittstelle auswählen.
Der Unterschied zwischen BeanFactory und ApplicationContext ist folgender:
Mit BeanFactory:
BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml")); Triangle triangle =(Triangle)beanFactory.getBean("triangle");
sing ApplicationContext:
ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml") Triangle triangle =(Triangle)beanFactory.getBean("triangle");
BeanFactory und ApplicationContext beides sind Möglichkeiten, um Bohnen aus Ihrem Spring-Container zu holen IOC aber es gibt immer noch einige Unterschied.
BeanFactory ist der eigentliche Container, der eine Reihe von Beans instanziiert, konfiguriert und verwaltet. Diese Beans arbeiten normalerweise zusammen und sind daher voneinander abhängig. Diese Abhängigkeiten spiegeln sich in den von BeanFactory verwendeten Konfigurationsdaten wider.
BeanFactory und ApplicationContext sind beide Java Schnittstellen und ApplicationContext erweitert BeanFactory. Beide sind Konfigurationen mit Hilfe von XML-Konfigurationsdateien Inversion von Steuerungs--- (IoC) und Abhängigkeitsinjektions--- ([~ # ~] di [~ # ~]) -Funktionen, während ApplicationContext erweiterte -Funktionen bereitstellt.
Eine BeanFactory wird durch die Schnittstelle "org.springframework.beans.factory" dargestellt, für die es mehrere Implementierungen gibt.
ClassPathResource resource = new ClassPathResource("appConfig.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
UNTERSCHIED
BeanFactory Bean instanziieren, wenn Sie getBean () aufrufen, während ApplicationContext die Singleton-Bean instanziiert, wenn der Container gestartet wird. Es wird nicht auf den Aufruf von getBean () gewartet.
BeanFactory unterstützt die Internationalisierung nicht, aber ApplicationContext unterstützt sie.
Ein weiterer Unterschied zwischen BeanFactory und ApplicationContext besteht in der Möglichkeit, Ereignisse für Beans zu veröffentlichen, die als Listener registriert sind.
Eine der populären Implementierungen von BeanFactory ist XMLBeanFactory, während eine der populären Implementierungen von ApplicationContextClassPathXmlApplicationContext ist.
Wenn Sie die automatische Verkabelung verwenden und BeanFactory verwenden, müssen Sie AutoWiredBeanPostProcessor mithilfe einer API registrieren, die Sie in XML konfigurieren können, wenn Sie ApplicationContext verwenden. Zusammenfassend ist BeanFactory für Testzwecke und Nichtproduktionszwecke in Ordnung, aber ApplicationContext ist eine funktionsreichere Containerimplementierung und sollte gegenüber BeanFactory bevorzugt werden
BeanFactory standardmäßig seine Unterstützung Lazy Laden und ApplicationContext standardmäßig Unterstützung Aggresive Laden.
Funktionsmatrix von Bean Factory im Vergleich zum Anwendungskontext Quelle: Spring Docs
Screenshot der Funktionen von BeanFacotry und ApplicationContext
ein. Ein Unterschied zwischen Bean-Factory und Anwendungskontext besteht darin, dass die Bean erst dann instanziiert wird, wenn Sie die Methode getBean () aufrufen, während ApplicationContext die Singleton-Bean instanziiert, wenn der Container gestartet wird. Es wird nicht auf den Aufruf von getBean gewartet.
b.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
oder
ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml};
Sie können je nach Projektanforderung eine oder mehrere XML-Dateien verwenden. Da ich hier zwei XML-Dateien verwende, d. H. Eine für Konfigurationsdetails für Serviceklassen, andere für Dao-Klassen. Hier ist ClassPathXmlApplicationContext dem ApplicationContext untergeordnet.
c. BeanFactory Container ist ein einfacher Container, der nur Objekte erstellen und Abhängigkeiten einfügen kann. Wir können jedoch keine anderen Dienste wie Sicherheit, Transaktionen, Nachrichten usw. hinzufügen, um alle Dienste bereitzustellen, die wir für die Verwendung von ApplicationContext Container benötigen.
d. BeanFactory bietet keine Unterstützung für die Internationalisierung, d. H. I18n, aber ApplicationContext bietet Unterstützung dafür.
e. BeanFactory Container unterstützt die AutoScanning-Funktion (Support Annotation based Dependency Injection) nicht, ApplicationContext Container jedoch.
f. Beanfactory Container erstellt erst zum Anforderungszeitpunkt ein Bean-Objekt. Dies bedeutet, dass Beanfactory Container Bohnen träge lädt. Während ApplicationContext Container Objekte von Singleton Bean nur zum Zeitpunkt des Ladens erstellt. Dies bedeutet, dass frühzeitig geladen wird.
g. Beanfactory Container unterstützen nur zwei Bereiche (Singleton & Prototyp) der Beans. ApplicationContext Container unterstützt jedoch den gesamten Beans-Bereich.
Grundsätzlich können wir Spring Container Objekte auf zwei Arten erstellen
beides sind die Schnittstellen
mit Hilfe von Implementierungsklassen können wir Objekte für Springcontainer erstellen
kommen wir zu den Unterschieden
BeanFactory
Unterstützt nicht die auf Annotation basierende Abhängigkeitsinjektion.
Unterstützt kein I18N
Standardmäßig unterstützt es Lazy Loading
es ist nicht möglich, mehrere Konfigurationsdateien zu konfigurieren.
beispiel: BeanFactory context = new XmlBeanFactory (neue Ressource ("applicationContext.xml"));
Anwendungskontext
Support Annotation-basierte Abhängigkeit [email protected], @PreDestroy
Unterstützung I18N
standardmäßig wird das aggressive Laden unterstützt.
es ermöglicht die Konfiguration mehrerer Konfigurationsdateien.
ex:
ApplicationContext context = new ClasspathXmlApplicationContext ("applicationContext.xml");
In einem Echtzeitszenario ist der Unterschied zwischen dem Spring IOC Core-Container (BeanFactory) und dem Advanced J2EE-Container (ApplicationContext) wie folgt.
BeanFactory erstellt Objekte für die Beans (d. H. Für POJO-Klassen), die in der Datei spring.xml (<bean></bean>
) nur, wenn Sie die .getBean () -Methode aufrufen, während ApplicationContext die Objekte für alle Beans erstellt (<bean></bean>
, wenn der Gültigkeitsbereich nicht explizit als "Prototype" angegeben ist), der in der Datei spring.xml konfiguriert wurde, während die Datei spring.xml selbst geladen wurde.
BeanFactory: (Lazy Container, da die Objekte für die Beans nur erstellt werden, wenn Sie explizit von der Benutzer-/Hauptklasse aufrufen.)
/*
* 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: (Eifriger Container, da beim Laden der Datei spring.xml die Objekte aller Singleton-Beans erstellt werden.)
ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
Technisch wird die Verwendung von ApplicationContext empfohlen, da in Echtzeitanwendungen die Bean-Objekte erstellt werden, während die Anwendung auf dem Server selbst gestartet wird. Dies verringert die Antwortzeit für die Benutzeranforderung, da die Objekte bereits für die Antwort verfügbar sind.
ApplicationContext ist ein großer Bruder von BeanFactory und all dies und noch viele andere Dinge, die BeanFactory zu bieten hat.
Zusätzlich zu den standardmäßigen org.springframework.beans.factory.BeanFactory-Lebenszyklusfunktionen erkennen und rufen ApplicationContext-Implementierungen ApplicationContextAware-Beans sowie ResourceLoaderAware-, ApplicationEventPublisherAware- und MessageSourceAware-Beans auf.
Verweisen Sie auf dieses Dokument von Spring Docs:
5.15.1 BeanFactory oder ApplicationContext?
Verwenden Sie einen ApplicationContext, es sei denn, Sie haben einen guten Grund, dies nicht zu tun.
Da der ApplicationContext alle Funktionen der BeanFactory enthält, wird er im Allgemeinen gegenüber der BeanFactory empfohlen, mit Ausnahme einiger Situationen, wie in einem Applet, in denen der Speicherverbrauch kritisch sein kann und einige zusätzliche Kilobyte den Unterschied ausmachen. Für die meisten typischen Unternehmensanwendungen und -systeme ist ApplicationContext jedoch genau das, was Sie verwenden möchten. In Spring 2.0 und höher wird der BeanPostProcessor-Erweiterungspunkt stark genutzt (um das Proxying usw. zu bewirken). Wenn Sie nur eine einfache BeanFactory verwenden, wird eine angemessene Menge an Unterstützung wie Transaktionen und AOP nicht wirksam, zumindest nicht ohne einige zusätzliche Schritte von Ihrer Seite. Diese Situation kann verwirrend sein, da an der Konfiguration nichts falsch ist.
In Summe:
Der ApplicationContext enthält alle Funktionen der BeanFactory. Es wird allgemein empfohlen, die erstere zu verwenden.
Es gibt einige eingeschränkte Situationen, z. B. in einer Mobilanwendung, in denen der Speicherverbrauch kritisch sein kann.
In diesen Fällen kann es gerechtfertigt sein, die leichtere BeanFactory zu verwenden. In den meisten Unternehmensanwendungen möchten Sie jedoch den ApplicationContext verwenden.
Weitere Informationen finden Sie in meinem Blog-Beitrag:
verwenden Sie BeanFactory nicht für Webanwendungen, da es nur Singleton- und Prototype-Bean-Scopes unterstützt.
Während der ApplicationContext-Container alle Bean-Bereiche unterstützt, sollten Sie ihn für Webanwendungen verwenden.
Ich denke, es ist erwähnenswert, dass Sie seit Frühjahr 3, wenn Sie eine Fabrik erstellen möchten, auch die @configuration
Anmerkung kombiniert mit dem richtigen @scope
@Configuration
public class MyFactory {
@Bean
@Scope("prototype")
public MyClass create() {
return new MyClass();
}
}
Ihre Fabrik sollte durch Spring Container mit der @ComponentScan
Anmerkung oder XML-Konfiguration