CodeGym /Java-Blog /Random-DE /Frühling für faule Leute. Grundlagen, grundlegende Konzep...
John Squirrels
Level 41
San Francisco

Frühling für faule Leute. Grundlagen, grundlegende Konzepte und Beispiele mit Code. Teil 2

Veröffentlicht in der Gruppe Random-DE
Im vorherigen Artikel habe ich kurz erklärt, was Frühling ist und was Bohnen und Kontext sind. Jetzt ist es Zeit, es auszuprobieren. Ich werde es mit IntelliJ IDEA Enterprise Edition machen. Alle meine Beispiele sollten aber auch in der kostenlosen IntelliJ IDEA Community Edition funktionieren. Wenn Sie in den Screenshots sehen, dass ich ein Fenster habe, das Sie nicht haben, machen Sie sich keine Sorgen – es ist für dieses Projekt nicht wichtig :) Frühling für faule Leute. Grundlagen, grundlegende Konzepte und Beispiele mit Code.  Teil 2 - 1Erstellen Sie zunächst ein leeres Maven-Projekt. Wie das geht, habe ich im Artikel unter diesem Link gezeigt . Lesen Sie bis zu den Worten „ Es ist Zeit für uns, unser Maven-Projekt in ein Webprojekt umzuwandeln. “ – danach zeigt der Artikel, wie man ein Webprojekt erstellt, aber das brauchen wir im Moment nicht. Im src/main/javaOrdner, erstellen Sie ein Paket (in meinem Fall habe ich es „ genannt) en.codegym.info.fatfaggy.animals. Sie können es nennen, wie Sie wollen. Vergessen Sie nur nicht, meinen Paketnamen an den richtigen Stellen durch Ihren Paketnamen zu ersetzen. Erstellen Sie nun die MainKlasse und fügen Sie eine hinzu Methode

public static void main(String[] args) {
    ...
}
Öffnen Sie anschließend die Datei pom.xml und fügen Sie den dependenciesAbschnitt hinzu. Gehen Sie nun zum Maven-Repository und suchen Sie den Spring-Kontext für die neueste stabile Version. Tragen Sie in den Abschnitt ein, was wir finden dependencies. Ich habe diesen Prozess in diesem anderen CodeGym-Artikel ausführlicher beschrieben (siehe Abschnitt mit dem Titel „ Abhängigkeiten in Maven verbinden “). Dann findet Maven selbst die erforderlichen Abhängigkeiten und lädt sie herunter. Am Ende sollten Sie etwa Folgendes erhalten: Frühling für faule Leute. Grundlagen, grundlegende Konzepte und Beispiele mit Code.  Teil 2 - 2Im Fenster links sehen Sie die Projektstruktur mit dem Paket und der MainKlasse. Das mittlere Fenster zeigt, wie pom.xml für mich aussieht. Ich habe auch Eigenschaften hinzugefügtAbschnitt dazu. In diesem Abschnitt wird Maven mitgeteilt, welche Java-Version ich in meinen Quelldateien verwende und welche Version kompiliert werden soll. Dies dient nur dazu, dass IDEA mich nicht warnt, dass ich eine alte Java-Version verwende. Dies ist optional :) Das rechte Fenster macht deutlich, dass, obwohl wir nur das Spring-Context-Modul verbunden haben, automatisch die Module Spring-Core, Spring-Beans, Spring-Aop und Spring-Expression eingezogen wurden. Wir hätten jedes Modul einzeln verbinden und für jedes Modul eine Abhängigkeit mit der expliziten Version in der pom.xml-Datei schreiben können, aber im Moment sind wir mit den Dingen so zufrieden, wie sie sind. Erstellen Sie nun das entitiesPaket und erstellen Sie darin drei Klassen: Cat, Dog, Parrot. Geben wir jedem Tier einen Namen (private String name— Sie können dort einige Werte fest codieren). Die Getter/Setter sind öffentlich. Nun wenden wir uns der MainKlasse und der main()Methode zu und schreiben etwa Folgendes:

public static void main(String[] args) {
	// Create an empty Spring context that will look for its own beans based on the annotations in the specified package
	ApplicationContext context = 
		new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.entities");

	Cat cat = context.getBean(Cat.class);
	Dog dog = (Dog) context.getBean("dog");
	Parrot parrot = context.getBean("parrot-polly", Parrot.class);

	System.out.println(cat.getName());
	System.out.println(dog.getName());
	System.out.println(parrot.getName());
}
Zuerst erstellen wir ein Kontextobjekt, das dem Konstruktor mitteilt, in welchem ​​Paket nach Beans gesucht werden soll. Mit anderen Worten: Spring wird dieses Paket durchgehen und versuchen, Klassen zu finden, die mit speziellen Anmerkungen gekennzeichnet sind, die darauf hinweisen, dass es sich um Beans handelt. Dann erstellt es die Objekte dieser Klassen und stellt sie in den Kontext. Danach erhalten wir eine Katze aus diesem Kontext. Wir rufen das Kontextobjekt auf, um uns eine Bean (ein Objekt) zu geben, die die Klasse des gewünschten Objekts angibt (wir können übrigens auch Schnittstellen angeben, nicht nur Klassen). Danach gibt Spring ein Objekt der angeforderten Klasse zurück, das wir dann in einer Variablen speichern. Als nächstes bitten wir Spring, uns eine Bohne namens „Hund“ zu besorgen. Wenn der Frühling einDogObjekt, gibt es dem Objekt einen Standardnamen (es sei denn, der erstellten Bean wurde explizit ein Name zugewiesen), der der Klassenname ist, jedoch mit einem Kleinbuchstaben am Anfang. In diesem Fall heißt unsere Klasse Dog, der Name der Bean lautet also „Hund“. Wenn wir BufferedReaderdort ein Objekt benötigen würden, würde Spring es „bufferedReader“ nennen. Und da Java nicht hundertprozentig sicher sein kann, welche Klasse wir wollen, gibt es ein ObjectObjekt zurück, das wir dann manuell in den gewünschten Typ umwandeln, d. hDog. Bequemer ist die Option, bei der die Klasse explizit angegeben wird. Die dritte Möglichkeit besteht darin, eine Bean anhand des Klassennamens und des Bean-Namens abzurufen. Es ist möglich, dass der Kontext mehrere Beans einer einzelnen Klasse enthält. Um die bestimmte Bohne anzugeben, die wir benötigen, geben wir ihren Namen an. Da wir hier auch die Klasse explizit angeben, müssen wir keinen Cast mehr durchführen. WICHTIG!Wenn Spring mehrere Beans findet, die unseren Anforderungen entsprechen, kann es nicht bestimmen, welche Bean es uns geben soll, und löst daher eine Ausnahme aus. Um diese Situation zu vermeiden, sollten Sie daher versuchen, Spring so genau wie möglich mitzuteilen, welche Bean Sie benötigen. Wenn Spring seinen Kontext durchsucht und keine einzelne Bean findet, die unseren Anforderungen entspricht, wird ebenfalls eine Ausnahme ausgelöst. Abschließend zeigen wir einfach die Namen unserer Tiere an, um zu überprüfen, ob wir wirklich die benötigten Gegenstände erhalten haben. Aber wenn wir das Programm jetzt ausführen, werden wir feststellen, dass Spring unglücklich ist – es kann die Tiere, die wir in seinem Kontext benötigen, nicht finden. Dies liegt daran, dass diese Bohnen nicht erstellt wurden. Wie ich bereits sagte, sucht Spring beim Scannen von Klassen nach seinen eigenen Spring-Annotationen. Und wenn Spring diese Anmerkungen nicht findet, dann nicht. Ich glaube nicht, dass diese Klassen den Beans entsprechen, die erstellt werden müssen. Um dies zu beheben, muss lediglich das hinzugefügt werden@ComponentAnmerkung vor jeder unserer Tierklassen.

@Component
public class Cat {
	private String name = "Oscar";
	...
}
Aber es gibt noch mehr. Wenn wir Spring explizit mitteilen müssen, dass die Bean für diese Klasse einen bestimmten Namen haben soll, geben wir den Namen in Klammern nach der Annotation an. Um Spring beispielsweise anzuweisen, parrot-pollyder Papageienbohne den Namen „ “ zu geben, den wir verwenden werden, um diesen Papagei in die mainMethode zu bekommen, sollten wir etwa Folgendes tun:

@Component("parrot-polly")
public class Parrot {
	private String name = "Polly";
	...
}
Das ist der Sinn der automatischen Konfiguration . Sie schreiben Ihre Klassen, markieren sie mit den erforderlichen Anmerkungen und teilen Spring das Paket mit, das Ihre Klassen enthält. Dies ist das Paket, das das Framework durchläuft, um Anmerkungen zu finden und Objekte dieser Klassen zu erstellen. Spring sucht übrigens nicht nur nach @ComponentAnnotationen, sondern auch nach allen anderen Annotationen, die diese erben. Zum Beispiel , @Controller, @RestController, @Serviceund @Repositorymehr, die wir in zukünftigen Artikeln vorstellen werden. Jetzt versuchen wir, dasselbe mit der Java-basierten Konfiguration zu erreichen . Entfernen Sie zunächst die@ComponentAnmerkungen aus unseren Kursen. Um die Sache noch anspruchsvoller zu machen, stellen Sie sich vor, dass wir diese Klassen nicht geschrieben haben und sie daher nicht einfach ändern können, was bedeutet, dass wir keine Anmerkungen hinzufügen können. Es ist, als wären diese Klassen in einer Bibliothek gepackt. In diesem Fall gibt es für uns keine Möglichkeit, diese Klassen so zu bearbeiten, dass sie von Spring erkannt werden. Aber wir brauchen Objekte dieser Klassen! Hier benötigen wir eine Java-basierte Konfiguration, um die Objekte zu erstellen. Erstellen Sie zunächst ein Paket mit einem Namen wie configs. Erstellen Sie in diesem Paket eine gewöhnliche Java-Klasse, etwa MyConfig, und markieren Sie sie mit der @ConfigurationAnnotation.

@Configuration
public class MyConfig {
}
Jetzt müssen wir die main()Methode optimieren und die Art und Weise ändern, wie wir den Kontext erstellen. Wir können entweder explizit angeben, welche Klasse unsere Konfiguration hat:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class);
Wenn wir mehrere verschiedene Klassen haben, die Beans erstellen, und wir mehrere davon gleichzeitig verbinden möchten, geben wir sie dort einfach alle an, getrennt durch Kommas:

ApplicationContext context =
	new AnnotationConfigApplicationContext(MyConfig.class, MyAnotherConfig.class);
Und wenn wir zu viele davon haben und sie alle gleichzeitig verbinden möchten, geben wir einfach den Namen des Pakets an, in dem sie enthalten sind:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.configs");
In diesem Fall durchsucht Spring das Paket und findet alle mit der @ConfigurationAnnotation gekennzeichneten Klassen. Nun, und wenn wir ein wirklich großes Programm haben, in dem die Konfigurationen in verschiedene Pakete unterteilt sind, dann geben wir einfach eine durch Kommas getrennte Liste mit Namen der Pakete an, die die Konfigurationen enthalten:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals.database.configs",
		"en.codegym.info.fatfaggy.animals.root.configs",
		"en.codegym.info.fatfaggy.animals.web.configs");
Oder der Name eines Pakets, das allen gemeinsam ist:

ApplicationContext context =
	new AnnotationConfigApplicationContext("en.codegym.info.fatfaggy.animals");
Sie können es machen, wie Sie wollen, aber mir scheint, dass die allererste Option, die einfach eine Klasse mit den Konfigurationen angibt, am besten zu unserem Programm passt. Beim Erstellen eines Kontexts sucht Spring nach Klassen, die mit der @ConfigurationAnnotation gekennzeichnet sind, und erstellt eigene Objekte dieser Klassen. Es wird versucht, Methoden aufzurufen, die mit der @BeanAnnotation gekennzeichnet sind. Das bedeutet, dass diese Methoden Beans (Objekte) zurückgeben, die Spring dem Kontext hinzufügt. Und jetzt erstellen wir in unserer Klasse Beans für eine Katze, einen Hund und einen Papagei mit Java-basierter Konfiguration. Das geht ganz einfach:

@Bean
public Cat getCat() {
	return new Cat();
}
Hier erstellen wir unsere Katze manuell und übergeben sie an Spring, der dann unser Objekt in seinem Kontext hält. Da wir unserem Bean keinen expliziten Namen gegeben haben, wird Spring ihm denselben Namen wie den Namen der Methode geben. In unserem Fall heißt die Katzenbohne „ getCat“. Da wir jedoch die Klasse und nicht den Namen verwenden, um die Cat-Bean in der Methode abzurufen main, ist der Name der Bean für uns nicht wichtig. Erstellen Sie auf ähnliche Weise eine Dog-Bean. Beachten Sie dabei, dass Spring der Bean den Methodennamen gibt. Um unsere Papageienbohne explizit zu benennen, geben wir nach der @BeanAnmerkung einfach ihren Namen in Klammern an:

@Bean("parrot-polly")
public Object weNeedMoreParrots() {
	return new Parrot();
}
Wie Sie sehen, habe ich hier einen ObjectRückgabetyp angegeben und der Methode einen beliebigen Namen gegeben. Dies hat keine Auswirkungen auf den Namen der Bean, da wir den Namen hier explizit angegeben haben. Dennoch ist es besser, einen mehr oder weniger aussagekräftigen Rückgabewert und Methodennamen anzugeben. Tun Sie dies aus keinem anderen Grund, als sich selbst einen Gefallen zu tun, wenn Sie das Projekt in einem Jahr wieder eröffnen. :) Betrachten Sie nun die Situation, in der wir eine Bean benötigen, um eine andere Bean zu erstellen . Angenommen, wir möchten, dass der Name der Katze in der Katzenbohne der Name des Papageis plus die Zeichenfolge „-killer“ ist. Kein Problem!

@Bean
public Cat getCat(Parrot parrot) {
	Cat cat = new Cat();
	cat.setName(parrot.getName() + "-killer");
	return cat;
}
Hier wird Spring erkennen, dass das Framework zum Erstellen dieser Bean die zuvor erstellte Parrot-Bean übergeben muss. Dementsprechend wird die notwendige Kette von Methodenaufrufen arrangiert: Zuerst wird die Papagei-erzeugende Methode aufgerufen und dann übergibt das Framework den neuen Papagei an die Katze-erzeugende Methode. Hier kommt die Abhängigkeitsinjektion ins Spiel: Spring selbst übergibt die erforderliche Papageienbohne an unsere Methode. Wenn sich IDEA über die Variable aufregt parrot, vergessen Sie nicht, den Rückgabetyp der Parrot-Erstellungsmethode von Objectin zu ändern Parrot. Darüber hinaus können Sie mit der Java-basierten Konfiguration absolut jeden Java-Code ausführenin Ihren Bean-Erstellungsmethoden. Sie können wirklich alles tun: andere Hilfsobjekte erstellen, beliebige andere Methoden aufrufen, auch solche, die nicht mit Spring-Annotationen gekennzeichnet sind, Schleifen erstellen, boolesche Bedingungen – was auch immer Ihnen in den Sinn kommt! Dies ist mit der automatischen Konfiguration nicht alles möglich, und noch weniger mit der XML-Konfiguration. Betrachten wir nun ein Problem, das etwas mehr Spaß macht. Polymorphismus und Schnittstellen :) Wir erstellen eine WeekDaySchnittstelle und erstellen 7 Klassen, die diese Schnittstelle implementieren: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday. Wir geben der Schnittstelle eine String getWeekDayName()Methode, die den Namen des Wochentags für die entsprechende Klasse zurückgibt. Mit anderen Worten, die MondayKlasse gibt „Monday" usw. Angenommen, unsere Aufgabe besteht beim Starten der Anwendung darin, eine Bean, die dem aktuellen Wochentag entspricht, in den Kontext einzufügen. Nicht Beans für alle Klassen, die die Schnittstelle implementieren, sondern nur die eine Bean, die wir benötigen. Das können WeekDaySie Mach das ungefähr so:

@Bean
public WeekDay getDay() {
	DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
	switch (dayOfWeek) {
		case MONDAY: return new Monday();
		case TUESDAY: return new Tuesday();
		case WEDNESDAY: return new Wednesday();
		case THURSDAY: return new Thursday();
		case FRIDAY: return new Friday();
		case SATURDAY: return new Saturday();
		default: return new Sunday();
	}
}
Hier ist der Rückgabetyp unsere Schnittstelle. Die Methode gibt abhängig vom aktuellen Wochentag ein echtes Objekt einer der Klassen zurück, die die Schnittstelle implementieren. Jetzt können wir in der Methode Folgendes tun main():

WeekDay weekDay = context.getBean(WeekDay.class);
System.out.println("Today is " + weekDay.getWeekDayName() + "!");
Bei mir sagt mir das Programm, dass es Sonntag ist :) Ich bin zuversichtlich, dass der Kontext ein völlig anderes Objekt enthalten wird, wenn ich das Programm morgen ausführe. Beachten Sie, dass wir die Bean einfach über die Schnittstelle abrufen: context.getBean(WeekDay.class). Spring durchsucht seinen Kontext nach der Bean, die die Schnittstelle implementiert, und gibt sie zurück. Dann stellt sich heraus, dass unsere WeekDayVariable am Ende ein Sonntagsobjekt ist und das bekannte Konzept des Polymorphismus gilt, wenn wir mit dieser Variablen arbeiten. :) Nun ein paar Worte zum kombinierten Ansatz , bei dem einige Beans automatisch von Spring erstellt werden, andere durch das Scannen von Paketen nach Klassen mit der @ComponentAnnotation und andere durch eine Java-basierte Konfiguration. Während wir darüber nachdenken, kehren wir zur Originalversion zurück, in der die Cat, DogundParrotKlassen wurden mit der Anmerkung gekennzeichnet @Component. Angenommen, wir möchten Beans für unsere Tiere erstellen, indem Spring das Paket automatisch scanntentities , aber wir möchten auch eine Bean mit dem Wochentag erstellen, wie wir es gerade getan haben. Alles, was Sie tun müssen, ist, die @ComponentScanAnnotation auf der Ebene der MyConfigKlasse hinzuzufügen, die wir beim Erstellen des Kontexts in angeben main(), und in Klammern das Paket anzugeben, das gescannt werden muss, und Beans der erforderlichen Klassen automatisch zu erstellen:

@Configuration
@ComponentScan("en.codegym.info.fatfaggy.animals.entities")
public class MyConfig {
	@Bean
	public WeekDay getDay() {
		DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
		switch (dayOfWeek) {
			case MONDAY: return new Monday();
			case TUESDAY: return new Tuesday();
			case WEDNESDAY: return new Wednesday();
			case THURSDAY: return new Thursday();
			case FRIDAY: return new Friday();
			case SATURDAY: return new Saturday();
			default: return new Sunday();
		}
	}
}
Beim Erstellen des Kontexts erkennt Spring, dass die Klasse verarbeitet werden muss MyConfig. en.codegym.info.fatfaggy.animals.entitiesEs betritt die Klasse und stellt fest, dass es das Paket „ “ scannen und Beans dieser Klassen erstellen muss . Anschließend führt es die Methode MyConfigder Klasse aus und fügt dem Kontext ein Bean hinzu. In der Methode haben wir nun Zugriff auf alle Bohnen, die wir brauchen: sowohl Tierobjekte als auch eine Bohne mit dem Wochentag. Wenn Sie Spring jemals dazu bringen müssen, auch einige XML-Konfigurationsdateien abzurufen, können Sie Ihre eigene Websuche durchführen, um eine Erklärung zu finden :) Zusammenfassung:getDay()WeekDaymain()
  • Versuchen Sie, die automatische Konfiguration zu verwenden
  • Geben Sie während der automatischen Konfiguration den Namen des Pakets an, das die Klassen enthält, deren Beans erstellt werden müssen
  • @ComponentDiese Klassen sind mit der Annotation gekennzeichnet
  • Spring durchläuft alle diese Klassen, erstellt Objekte und stellt sie in den Kontext;
  • Wenn uns die automatische Konfiguration aus irgendeinem Grund nicht zusagt, verwenden wir eine Java-basierte Konfiguration
  • In diesem Fall erstellen wir eine gewöhnliche Java-Klasse, deren Methoden die benötigten Objekte zurückgeben. Wir markieren diese Klasse mit der @ConfigurationAnnotation, wenn wir das gesamte Paket scannen möchten, anstatt beim Erstellen des Kontexts eine bestimmte Klasse mit der Konfiguration anzugeben
  • Die Methoden dieser Klasse, die Beans zurückgeben, sind mit der @BeanAnnotation gekennzeichnet
  • Wenn wir das automatische Scannen bei Verwendung einer Java-basierten Konfiguration aktivieren möchten, verwenden wir die @ComponentScanAnnotation.
Wenn dieser Artikel völlig verwirrend war, lesen Sie ihn in ein paar Tagen noch einmal durch. Oder wenn Sie sich auf einer der ersten CodeGym-Stufen befinden, ist es für Sie möglicherweise etwas früh, sich mit Spring zu befassen. Sie können jederzeit zu einem späteren Zeitpunkt zu diesem Artikel zurückkehren, wenn Sie sich in Ihren Java-Programmierkenntnissen sicherer fühlen. Wenn alles klar ist, können Sie versuchen, eines Ihrer Lieblingsprojekte in Spring umzuwandeln :) Wenn einige Dinge klar sind, andere jedoch nicht, hinterlassen Sie bitte einen Kommentar :) Teilen Sie mir Ihre Vorschläge und Kritik mit, falls ich einen Fehler gemacht habe Irgendwo oder etwas Unsinn geschrieben :) Im nächsten Artikel werden wir uns abrupt mit spring-web-mvc befassen und eine einfache Webanwendung mit Spring erstellen.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION