Vorbereitung auf die Spring Professional-Zertifizierung. Behälter, IoC, Bohnen

Guten Tag, Habr.


Heute habe ich beschlossen, Ihnen eine Übersetzung einer Reihe von Artikeln zur Vorbereitung auf die Spring Professional-Zertifizierung vorzulegen .


Diese Übersetzung ist nur der erste Artikel. Wenn sie an das Publikum geht, werde ich weiterhin Übersetzungen herausgeben.


Warum mache ich das, weil es bereits eine Reihe von Spezialmaterialien gibt?
  1. Oft sind die darin enthaltenen Informationen nicht strukturiert, nicht gesammelt oder nicht relevant
  2. Junge Entwickler sprechen möglicherweise kein Englisch. Dieser Zyklus kann nicht nur zur Zertifizierung, sondern auch zum Selbsttraining / zur Wiederholung von Materialien verwendet werden.
  3. Diese Materialien können zur Vorbereitung des Interviews verwendet werden Sie sind in Form von Fragen und Antworten angeordnet.
  4. Ein wichtiger und wichtigster Vorteil ist, dass diese Qualitätssicherung aus Fragen des offiziellen Pivotal Study Guide besteht .

  • Ich habe absichtlich einige Fragen übersehen, die mir überflüssig erschienen oder die nicht im Leitfaden enthalten waren .

Inhaltsverzeichnis
  1. Abhängigkeitsinjektion, Container, IoC, Bohnen
  2. AOP (aspektorientierte Programmierung)
  3. JDBC, Transaktionen, JPA, Federdaten
  4. Frühlingsstiefel
  5. Frühling mvc
  6. Frühlingssicherheit
  7. RUHE
  8. Testen


Ich werde eine Liste von Quellen schreiben, aus denen der Autor Materialien entnommen hat
  • Spring 5 Designmuster
  • Frühling in Aktion 4. Auflage
  • Spring Security - Dritte Ausgabe
  • Core Spring 5-Zertifizierung im Detail von Ivan Krizsan
  • Spring Documentation und Spring API Javadocs

Also, fangen wir an.


Was ist Abhängigkeitsinjektion (DI) und welche Vorteile bietet sie?

Die Abhängigkeitsinjektion ist ein spezielles Muster, das die Kommunikation zwischen Federkomponenten reduziert. Wenn Sie DI anwenden, wird Ihr Code sauberer, einfacher und leichter zu verstehen und zu testen.
Gemäß dem DI-Muster wird das Erstellen von Objekten für Abhängigkeiten an die Fabrik übertragen oder an einen Dritten übergeben. Dies bedeutet, dass wir uns darauf konzentrieren können, diese Objekte zu verwenden, anstatt sie zu erstellen.


DI Vorteile
  • Reduzierte Kommunikation zwischen Teilen der Anwendung
  • Verbesserte Tests
  • Erweiterte Anwendungsarchitektur
  • Reduziert den Boilerplate-Code
  • Standardisiert die Anwendungsentwicklung

Warum werden Schnittstellen zum Erstellen von Spring Beans empfohlen?
  • Verbesserte Tests. In Tests kann die Bean durch ein spezielles Objekt (Mock oder Stub) ersetzt werden, das die Bean-Schnittstelle implementiert.
  • Ermöglicht die Verwendung des dynamischen Proxy-Mechanismus aus dem JDK (z. B. beim Erstellen eines Repositorys über Spring Data)
  • Ermöglicht das Ausblenden der Implementierung

Was ist der Anwendungskontext?

Im Spring Framework stellt die Schnittstelle org.springframework.factory.BeanFactory eine org.springframework.factory.BeanFactory Factory bereit, die gleichzeitig ein IoC-Anwendungscontainer ist. Das Bean-Management basiert auf der Konfiguration (Java oder XML).


Die Schnittstelle org.springframework.context.ApplicationContext ist ein Wrapper über eine Bean-Factory, der einige zusätzliche Funktionen wie AOP, Transaktionen, Sicherheit, i18n usw. bietet.


Was ist ein Container und wie ist sein Lebenszyklus?

Die Basis des Spring Frameworks ist ein Container, und unsere Objekte "leben" in diesem Container.
Ein Container erstellt normalerweise viele Objekte basierend auf ihren Konfigurationen und verwaltet ihren Lebenszyklus von der Erstellung eines Objekts bis zur Zerstörung.


Ein Container ist ein Objekt, das die ApplicationContext- Schnittstelle implementiert.


Container-Lebenszyklus
  1. Der Container wird beim Start der Anwendung erstellt.
  2. Der Container liest Konfigurationsdaten
  3. Die Beschreibung der Fächer wird aus den Konfigurationsdaten erstellt
  4. BeanFactoryPostProcessors verarbeiten die Bean-Beschreibung
  5. Der Container erstellt anhand ihrer Beschreibung Bohnen
  6. Beans werden initialisiert - Eigenschaftswerte und Abhängigkeiten werden in die Bean eingebettet
  7. BeanPostProcessor startet Rückrufmethoden
  8. Die Anwendung ist betriebsbereit
  9. Initialisierter Anwendungsabschluss
  10. Container schließt
  11. Rückrufmethoden werden aufgerufen

Wie erstelle ich eine Instanz von ApplicationContext?

Der Frühling bietet verschiedene Kontextvarianten.


Es gibt verschiedene grundlegende Implementierungen der ApplicationContext-Schnittstelle:


  • FileSystemXmlApplicationContext
  • ClassPathXmlApplicationContext
  • AnnotationConfigApplicationContext
  • XmlWebApplicationContext
  • AnnotationConfigWebApplicationContext

Beispiele zum Erstellen eines Kontexts:


 ApplicationContext ctx = new FileSystemXmlApplicationContext(                                     "c:/bean_properties.xml"); ApplicationContext ctx = new AnnotationConfigApplicationContext(                            "com.springdemoapp.JavaConfig.class"); 

Können Sie den Lebenszyklus einer Bohne in einem Behälter beschreiben?
  1. Laden von Bin-Beschreibungen, Erstellen eines Abhängigkeitsdiagramms (zwischen Beans)
  2. Erstellen und BeanFactoryPostProcessors
  3. Bohnen erstellen
  4. Spring fügt Werte und Abhängigkeiten in Bean-Eigenschaften ein
  5. Wenn die Bean die setBeanName() -Methode über die NameBeanAware-Schnittstelle implementiert, wird die Bean-ID an die Methode übergeben
  6. Wenn die Bean BeanFactoryAware implementiert, erstellt Spring über setBeanFactory() über diese Schnittstelle einen Verweis auf die Bean-Factory.
  7. Wenn die Bean die ApplicationContextAware-Schnittstelle implementiert, erstellt Spring über setApplicationContext() einen Verweis auf den ApplicationContext.
  8. BeanPostProcessor ist eine spezielle Schnittstelle (dazu weiter unten), und Spring ermöglicht es Bins, diese Schnittstelle zu implementieren. Durch Implementieren der postProcessBeforeInitialization() -Methode können Sie die Instanz der Bean ändern, bevor Sie sie initialisieren (die Bean) (Festlegen von Eigenschaften usw.).
  9. Wenn Rückrufmethoden definiert sind, ruft Spring sie auf. Dies ist beispielsweise eine Methode, die von @PostConstruct oder der initMethod Methode aus einer @Bean Annotation mit Anmerkungen versehen wurde.
  10. Die Bohne ist jetzt gebrauchsfertig. Es kann mit der ApplicationContext#getBean() -Methode abgerufen werden.
  11. Nachdem der Kontext geschlossen wurde (Methode close() aus ApplicationContext), wird die Bean zerstört.
  12. Wenn die Bean eine von @PreDestroy Anmerkungen versehene Methode @PreDestroy , wird diese Methode vor der Zerstörung aufgerufen. Wenn die Bean DisposibleBean implementiert, ruft Spring die Methode destroy() auf, um Ressourcen zu löschen oder Prozesse in der Anwendung abzubrechen. Wenn die @Bean Methode in der destroyMethod , wird sie auch aufgerufen.

Wie bekomme ich ApplicationContext in den Integrationstest?

Wenn Sie JUnit 5 verwenden, müssen Sie zwei Anmerkungen angeben:


  • @ExtendWith (TestClass.class) - wird verwendet, um eine Testklasse anzugeben
  • @ContextConfoguration (classes = JavaConfig.class) - Lädt die Java / XML-Konfiguration, um im Test einen Kontext zu erstellen

Sie können die Annotation @SpringJUnitConfig , die diese beiden Annotationen kombiniert.
Sie können die Annotation @SpringJUnitWebConfig verwenden, um die @SpringJUnitWebConfig zu testen.


Wie kann ich den Kontext in einer Anwendung herunterfahren?

Wenn dies keine Webanwendung ist, gibt es zwei Möglichkeiten:


  • Registrieren Sie shutdown-hook mit dem Methodenaufruf registerShutdownHook() . Es ist auch in der AbstractApplicationContext-Klasse implementiert. Dies ist die bevorzugte Methode.
  • Sie können die Methode close() aus der AbstractApplicationContext-Klasse aufrufen.

In der Spring Boot-Anwendung:


  • Spring Boot registriert den Shutdown-Hook selbst für Sie.

Was ist Java-Konfiguration? Wie wird es angewendet?

Um eine Klasse mit einer auf Java-Code basierenden Konfiguration zu erstellen, müssen Sie sie mit Anmerkungen versehen
@Configuration .
Diese Klasse enthält Factory-Methoden zum Erstellen von Beans im Container.
Diese Methoden sollten mit der Annotation @Bean .


Ein Beispiel:


 @Configuration public class DSConfig {  @Bean  public DataSource dataSource() {      return DataSourceBuilder          .create()          .username("")          .password("")          .url("")          .driverClassName("")          .build();  } } 

Diese Klasse platziert eine Instanz der DataSource-Klasse im Container. Später kann es beim Zugriff auf die Datenbank verwendet werden.


DI mit Anmerkungen, Klassenscannen

Komponentenscanning - Spring erkennt automatisch die Bohnen, die sich im Behälter befinden. Dies sind Behälter mit Anmerkungsstereotypen.


Das Scannen von Komponenten ist jedoch standardmäßig nicht aktiviert.
Um das Scannen zu aktivieren, kommentieren Sie die Klasse @ Configuration mit der Annotation @ComponentScanning . Spring scannt automatisch das Paket, das diese Klasse und alle ihre Unterpakete enthält.
Sie können andere Pakete zum Scannen und sogar Klassen angeben:


 // 2  @Configuration(basePackages = {"soundsystem", "video"}) 

 //  @Configuration(basePackageClasses = "MyClass.class") 

Autowiring - Spring fügt beim Scannen oder Platzieren eines Behälters in einem Container automatisch Abhängigkeiten ein.
Die Abhängigkeitsinjektion verwendet die Annotation @Autowire .


Was sind Stereotypen (Annotations-Stereotypen)?

Stereotype sind Anmerkungen, die spezielle Funktionen bezeichnen.
Alle Stereotypen enthalten @Component Annotation @Component .


KomponenteDie Root-Annotation, die eine Klasse als Kandidaten für die automatische Implementierung kennzeichnet
ControllerGibt an, dass die Klasse der Controller zum Senden von Daten an die Front ist.
@ RestControllerGibt an, dass die Klasse der Controller für REST ist.
Enthält Anmerkungen zu Controller und @ResponseBody
ServiceGibt an, dass die Klasse ein Dienst zum Ausführen von Geschäftslogik ist.
RepositoryGibt an, dass die Klasse ein Repository für die Arbeit mit der Datenbank ist.
@ KonfigurationGibt an, dass die Klasse eine Java-Konfiguration enthält (@ Bean-Methoden)

Was sind die Behälterbereiche? Was ist ihre Standardsichtbarkeit?

Geltungsbereich - Geltungsbereich. Es gibt 2 Standardbereiche.


Singleton
Der Standardbereich. Der Container enthält nur 1 Bean-Instanz
Prototyp
Der Container kann eine beliebige Anzahl von bin-Instanzen enthalten

Und 4 Bereiche in einer Webanwendung.


Anfrage
Umfang - 1 HTTP-Anforderung. Für jede Anforderung wird eine neue Bean erstellt.
Sitzung
Umfang - 1 Sitzung. Für jede Sitzung wird eine neue Bean erstellt.
Anwendung
Gültigkeitsbereich - ServletContext-Lebenszyklus
Web-Socket
Geltungsbereich - WebSocket-Lebenszyklus

Der Bereich wird mithilfe der @Scope Scope-Annotation für @Bean Methoden angegeben.


Wie hängen die verschiedenen Bereiche und das Multithreading zusammen?

Prototype Scope ist da nicht threadsicher Es kann nicht garantiert werden, dass dieselbe Instanz nur in einem Thread aufgerufen wird.


Singleton Scope hingegen ist threadsicher.


Wie entstehen Bohnen: sofort oder träge? Wie kann ich dieses Verhalten ändern?

Singleton-Beans werden normalerweise sofort nach dem Scannen erstellt.
Prototyp-Beans werden normalerweise nur auf Anfrage erstellt.


Sie können die @Lazy Annotation verwenden, um anzugeben, wie initialisiert werden soll.
Es wird auf @ Bean-Methoden, auf @ Configuration-Klassen oder auf @ Component-Klassen platziert.
Abhängig von dem Parameter (wahr oder falsch), den die Annotation akzeptiert, ist die Initialisierung entweder verzögert oder erfolgt sofort. Standardmäßig (d. H. Ohne Angabe eines Parameters) wird true verwendet.


Was passiert, wenn ein Behälter mit einem Bereich in einen Behälter mit einem anderen Bereich eingebettet ist?

Singleton Bean kann in jede andere Bean eingebettet werden.


Nur prototype oder singleton können in singleton eingebettet werden.
Wenn Sie einen Prototyp implementieren, wird für jeden Singleton ein eindeutiger Prototyp erstellt.


Der Prototyp kann eine Abhängigkeit für jede Bean sein.
Sie können nur Singleton oder Prototyp implementieren.


Was ist ein BeanFactoryPostProcessor und wann wird er verwendet?
  • BeanFactoryPostProcessor Bin-Beschreibungen oder Konfigurationsmetadaten, bevor der Bin erstellt wird.
  • Spring bietet mehrere nützliche BeanFactoryPostProcessor Implementierungen, z. B. das Lesen von Eigenschaftendateien und das BeanFactoryPostProcessor Eigenschaften.
  • Sie können Ihre eigene Implementierung von BFPP schreiben.

Warum benötigen Sie die static @ Bean-Methode?

Um benutzerdefiniertes BFPP zu verwenden. Sie können den Mechanismus zum Abrufen von Daten aus Metadateien überschreiben.


 @Bean public static PropertySourcesPlaceholderConfigurer pspc() {    //,    pspc } 

Beschreiben der Eigenschaften der @ Bean-Annotation
  • destroyMethod - verweist auf eine destroyMethod . Die Methode befindet sich im Papierkorb.
  • initMethod - verweist auf eine initMethod . Die Methode befindet sich im Papierkorb.
  • name - der Name der Bohne. Standardmäßig ist der Bean-Name der Methodenname.
  • value - Alias ​​für name ()

Was ist ein BeanPostProcessor und wie unterscheidet er sich von einem BeanFactoryPostProcessor?

Spring verwendet mehrere BeanPostProcessors.
Zum Beispiel CommonAnnotationPostProcessor oder AutowiredAnnotationBeanPostProcessor .
BPP arbeitet mit Bean-Instanzen, d.h. Der Container erstellt den Behälter, und dann startet BPP.



Was sind Rückrufmethoden und wie werden sie verwendet?

Es gibt 3 Möglichkeiten, solche Methoden zu erstellen:


  • Anmerkungen zu @PreDestroy und @PostConstruct
  • Die destroyMethod initMethod und destroyMethod in der Annotation destroyMethod , die auf Methoden in der Bean-Klasse verweisen
  • InitializingBean#afterPropertiesSet() und DisposableBean#destroy() . Um diese Methoden zu überschreiben, müssen Sie die entsprechenden Schnittstellen implementieren.


Wie kann ich die @ Autowire-Annotation verwenden und was ist der Unterschied zwischen den Methoden?

Die folgenden DI-Typen können in Ihrer Anwendung verwendet werden:


  • Konstruktor DI
  • Setter di
  • Feld di

DI durch den Konstruktor wird als der beste Weg angesehen, weil Für ihn besteht keine Notwendigkeit, Reflexion zu verwenden, und er hat auch nicht die Nachteile von DI durch den Setter.
DI durch das Feld wird nicht empfohlen, weil Hierzu wird eine Reflexion verwendet, die die Produktivität verringert.
DI durch den Konstruktor kann zu zirkulären Abhängigkeiten führen . Um dies zu vermeiden, können Sie die verzögerte Initialisierung von Beans oder DI über den Setter verwenden.


Beschreiben des Verhaltens der Annotation @Autowired
  1. Der Container bestimmt den Typ des einzubettenden Objekts.
  2. Ein Container sucht in einem Kontext (auch als Container bezeichnet) nach Beans, die dem gewünschten Typ entsprechen
  3. Wenn es mehrere Kandidaten gibt und einer von ihnen als @Primary markiert @Primary , wird er implementiert
  4. Wenn @Autowire + Qualifier Annotationen verwendet werden, verwendet der Container die Informationen von @Qualifier um herauszufinden, welche Komponente @Qualifier werden soll
  5. Andernfalls versucht der Container, die Komponente basierend auf ihrem Namen oder ihrer ID zu injizieren.
  6. Wenn keine der Methoden funktioniert hat, wird eine Ausnahme ausgelöst

Der Container verarbeitet den DI mithilfe eines AutowiredAnnotationBeanPostProcessor . In dieser Hinsicht kann die Annotation in keinem BeanFactoryPP oder BeanPP verwendet werden.


Wenn das injizierte Objekt ein Array, eine Sammlung oder eine Zuordnung mit einem generischen Objekt ist, bettet Spring alle Beans vom Typ in dieses Array (oder eine andere Datenstruktur) ein. Im Fall einer Karte ist der Schlüssel der Bean-Name.


 // ,   DI @Authowired(required = true/false) 

Wie mache ich DI in einem privaten Bereich?

Sie können verschiedene Arten der Implementierung verwenden:


  • Konstruktor
  • Setter
  • Feldinjektion
  • Wert

Wie ergänzt die Verwendung von @Qualifier @Autowired?

Spring bietet eine Qualifier- Annotation, um das DI-Mehrdeutigkeitsproblem zu überwinden.


 @Bean @Qualifier("SomeClass1") public SomeClass getField() {...} //… @Autowire @Qualifier("SomeField1") public SomeClass someField; 

Wenn der Container mehrere Bins desselben Typs (SomeClass) hat, implementiert der Container genau diesen Bin, über dessen @ Bean-Methode sich ein geeignetes Qualifikationsmerkmal befindet. Sie können einer Methode auch kein Qualifikationsmerkmal zuweisen, sondern den Bean-Namen als Qualifikationsparameter verwenden.
Der Bean-Name kann über den Bean- Annotation-Parameter angegeben werden. Standardmäßig ist dies der Name der Factory-Methode.


Was sind Proxy-Objekte und welche Arten von Proxy-Objekten kann Spring erstellen?

Ein Proxy ist ein spezielles Objekt, das dieselben öffentlichen Methoden wie die Bean hat, jedoch über zusätzliche Funktionen verfügt.
Zwei Arten von Proxies:


  • JDK-Proxy - dynamischer Proxy. APIs sind in das JDK integriert. Es braucht eine Schnittstelle
  • CGLib-Proxy - nicht in das JDK integriert. Wird verwendet, wenn die Schnittstelle eines Objekts nicht verfügbar ist.

Vorteile von Proxy-Objekten:


  • Erlaube, extra hinzuzufügen. Logik - Transaktionsmanagement, Sicherheit, Protokollierung
  • Trennt Code (Protokollierung usw.) von der Hauptlogik

Wie wird eine Singleton-Bean implementiert?

Befindet sich keine Bean-Instanz im Container, wird die @ Bean-Methode aufgerufen. Wenn eine Bean-Instanz vorhanden ist, wird die bereits erstellte Bean zurückgegeben.


Was sind Profile? Was sind ihre Gründe für die Verwendung?

Wenn Sie die Java-Konfiguration verwenden, können Sie die Annotation @Profile .
Je nach angegebenem Profil können Sie unterschiedliche Einstellungen für Spring verwenden.
Es kann in die Klassen @Configuration und Component sowie in die Bean- Methoden eingefügt werden.


 Profile("!test") //   ,   

 @Bean("dataSource") @Profile("production") public DataSource jndiDataSource() {...} @Bean("dataSource") @Profile("development") public DataSource standaloneDataSource() {...} 

Wie binde ich einfache Werte in Eigenschaften in Spring ein?

Sie können hierfür die Annotation @Value .
Solche Werte können aus Eigenschaftendateien, aus Behältern usw. erhalten werden.


 @Value("$some.key") public String stringWithDefaultValue; 

In diese Variable wird eine Zeichenfolge eingebettet, z. B. aus der Eigenschaft oder aus der Ansicht.


Bitte senden Sie wie gewohnt Korrekturen oder Fehler in PM.

Source: https://habr.com/ru/post/de470305/


All Articles