Préparation à la certification professionnelle du printemps. Conteneur, IoC, haricots

Bonjour, Habr.


Aujourd'hui, j'ai décidé de vous présenter une traduction d'une série d'articles en préparation de la certification professionnelle du printemps .


Cette traduction n'est que le premier article, si elle est destinée au public, je continuerai à publier des traductions.


Pourquoi est-ce que je fais ça, car il y a déjà un tas de matériel spécialisé?
  1. Souvent, les informations qu'ils contiennent ne sont ni structurées, ni collectées, ni pertinentes
  2. Les jeunes dĂ©veloppeurs ne connaissent peut-ĂȘtre pas l'anglais. Ce cycle peut ĂȘtre utilisĂ© non seulement pour la certification, mais aussi pour l'autoformation / rĂ©pĂ©tition des matĂ©riels.
  3. Ces documents peuvent ĂȘtre utilisĂ©s pour prĂ©parer l'entretien, comme ils sont organisĂ©s sous forme de questions et rĂ©ponses.
  4. Un avantage important et le plus important est que cet AQ est composé de questions du Guide officiel d' étude pivot.

  • J'ai dĂ©libĂ©rĂ©ment manquĂ© des questions qui me semblaient superflues ou qui n'Ă©taient pas dans le guide .

Table des matiĂšres
  1. Injection de dépendance, conteneur, IoC, haricots
  2. AOP (programmation orientée aspect)
  3. JDBC, transactions, JPA, données de printemps
  4. Botte de printemps
  5. Spring mvc
  6. Sécurité printaniÚre
  7. REPOS
  8. Test


Je vais écrire une liste de sources dont l'auteur a tiré des documents
  • Printemps 5 modĂšles de conception
  • Spring in Action 4e Ă©dition
  • Spring Security - Third Edition
  • La certification Core Spring 5 en dĂ©tail par Ivan Krizsan
  • Documentation Spring et javadocs API Spring

Commençons donc.


Qu'est-ce que l'injection de dépendance (DI) et quels sont ses avantages?

L'injection de dépendance est un modÚle spécial qui réduit la communication entre les composants Spring. Ainsi, lors de l'application de DI, votre code devient plus propre, plus simple, il devient plus facile à comprendre et à tester.
Selon le modÚle DI, la création d'objets pour les dépendances est transférée à l'usine ou donnée à un tiers. Cela signifie que nous pouvons nous concentrer sur l'utilisation de ces objets au lieu de les créer.


Avantages sociaux chez DI
  • Communication rĂ©duite entre les parties de l'application
  • AmĂ©lioration des tests
  • Architecture d'application amĂ©liorĂ©e
  • RĂ©duit le code passe-partout
  • Standardise le dĂ©veloppement d'applications

Pourquoi les interfaces sont-elles recommandées pour créer des beans Spring?
  • AmĂ©lioration des tests. Dans les tests, le bean peut ĂȘtre remplacĂ© par un objet spĂ©cial (mock ou stub) qui implĂ©mente l'interface du bean.
  • Vous permet d'utiliser le mĂ©canisme de proxy dynamique Ă  partir du JDK (par exemple, lors de la crĂ©ation d'un rĂ©fĂ©rentiel via Spring Data)
  • Vous permet de masquer l'implĂ©mentation

Qu'est-ce que le contexte d'application?

Dans Spring Framework, l'interface org.springframework.factory.BeanFactory fournit une fabrique de org.springframework.factory.BeanFactory , qui est en mĂȘme temps un conteneur IoC pour l'application. La gestion des beans est basĂ©e sur la configuration (java ou xml).


L'interface org.springframework.context.ApplicationContext est un wrapper sur une fabrique de beans qui fournit des fonctionnalités supplémentaires, telles que AOP, transactions, sécurité, i18n, etc.


Qu'est-ce qu'un conteneur et quel est son cycle de vie?

La base du Spring Framework est un conteneur, et nos objets "vivent" dans ce conteneur.
Un conteneur crée généralement de nombreux objets en fonction de leurs configurations et gÚre leur cycle de vie, de la création d'un objet à sa destruction.


Un conteneur est un objet qui implémente l'interface ApplicationContext .


Cycle de vie des conteneurs
  1. Le conteneur est créé au démarrage de l'application.
  2. Le conteneur lit les données de configuration
  3. La description des bacs est créée à partir des données de configuration
  4. BeanFactoryPostProcessors gĂšre la description du bean
  5. Le conteneur crée des beans en utilisant leur description
  6. Les beans sont initialisés - les valeurs des propriétés et les dépendances sont intégrées dans le bean
  7. Méthodes de rappel de démarrage de BeanPostProcessor
  8. L'application est opérationnelle
  9. ClÎture de l'application initialisée
  10. Le conteneur se ferme
  11. Les méthodes de rappel sont appelées

Comment créer une instance d'ApplicationContext?

Le printemps propose plusieurs variantes de contexte.


Il existe plusieurs implémentations de base de l'interface ApplicationContext:


  • FileSystemXmlApplicationContext
  • ClassPathXmlApplicationContext
  • AnnotationConfigApplicationContext
  • XmlWebApplicationContext
  • AnnotationConfigWebApplicationContext

Exemples de création d'un contexte:


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

Pouvez-vous décrire le cycle de vie d'un haricot dans un récipient?
  1. Chargement des descriptions de bacs, création d'un graphique de dépendance (entre les beans)
  2. Création et BeanFactoryPostProcessors
  3. Créer des haricots
  4. Spring injecte des valeurs et des dépendances dans les propriétés du bean
  5. Si le bean implémente la méthode setBeanName() partir de l'interface NameBeanAware, l'ID du bean est transmis à la méthode
  6. Si le bean implémente BeanFactoryAware, Spring établit une référence à la fabrique de bean via setBeanFactory() partir de cette interface.
  7. Si le bean implémente l'interface ApplicationContextAware, Spring établit une référence à ApplicationContext via setApplicationContext() .
  8. BeanPostProcessor est une interface spéciale (à ce sujet ci-dessous), et Spring permet aux beans d'implémenter cette interface. En implémentant la méthode postProcessBeforeInitialization() , vous pouvez modifier l'instance du bean avant de l'initialiser (le bean) (définition des propriétés, etc.)
  9. Si des méthodes de rappel sont définies, Spring les appelle. Par exemple, il s'agit d'une méthode annotée par @PostConstruct ou la méthode initMethod partir d'une annotation @Bean .
  10. Le haricot est maintenant prĂȘt Ă  l'emploi. Il peut ĂȘtre obtenu Ă  l'aide de la mĂ©thode ApplicationContext#getBean() .
  11. Une fois le contexte fermé (méthode close() d'ApplicationContext), le bean est détruit.
  12. Si le bean a une méthode annotée par @PreDestroy , cette méthode sera appelée avant la destruction. Si le bean implémente DisposibleBean, Spring appellera la méthode destroy() pour effacer les ressources ou tuer les processus dans l'application. Si la méthode @Bean est définie dans l' destroyMethod , elle est également appelée.

Comment obtenir ApplicationContext dans le test d'intégration?

Si vous utilisez JUnit 5, vous devez spécifier 2 annotations:


  • @ExtendWith (TestClass.class) - utilisĂ© pour indiquer une classe de test
  • @ContextConfoguration (classes = JavaConfig.class) - charge la configuration java / xml pour crĂ©er le contexte dans le test

Vous pouvez utiliser l'annotation @SpringJUnitConfig , qui combine ces deux annotations.
Vous pouvez utiliser l'annotation @SpringJUnitWebConfig pour tester la couche Web.


Comment fermer le contexte dans une application?

S'il ne s'agit pas d'une application Web, il existe deux façons:


  • Enregistrez shutdown-hook Ă  l'aide de l'appel de mĂ©thode registerShutdownHook() , il est Ă©galement implĂ©mentĂ© dans la classe AbstractApplicationContext. C'est la mĂ©thode prĂ©fĂ©rĂ©e.
  • Vous pouvez appeler la mĂ©thode close() partir de la classe AbstractApplicationContext.

Dans l'application Spring Boot:


  • Spring Boot enregistrera le crochet d'arrĂȘt pour vous tout seul.

Qu'est-ce que la configuration Java? Comment est-il appliqué?

Pour créer une classe avec une configuration basée sur du code Java, vous devez l'annoter avec
@Configuration .
Cette classe contiendra des méthodes d'usine pour créer des beans dans le conteneur.
Ces mĂ©thodes doivent ĂȘtre annotĂ©es avec l'annotation @Bean .


Un exemple:


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

Cette classe placera une instance de la classe DataSource dans le conteneur. Plus tard, il peut ĂȘtre utilisĂ© lors de l'accĂšs Ă  la base de donnĂ©es.


DI Ă  l'aide d'annotations, balayage de classe

Analyse des composants - Spring détecte automatiquement les grains qui seront dans le conteneur. Ce sont des bacs avec des annotations-stéréotypes.


Cependant, l'analyse des composants n'est pas activée par défaut.
Pour activer l'analyse, @ComponentScanning classe @ Configuration avec l'annotation @ComponentScanning . Spring analysera automatiquement le package contenant cette classe et tous ses sous-packages.
Vous pouvez spĂ©cifier d'autres packages pour l'analyse, et mĂȘme des classes:


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

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

Cùblage automatique - Spring injectera automatiquement les dépendances lors de la numérisation ou du placement d'un bac dans un conteneur.
L'injection de dépendances utilise l'annotation @Autowire .


Que sont les stéréotypes (annotations-stéréotypes)?

Les stéréotypes sont des annotations indiquant une fonctionnalité spéciale.
Tous les stéréotypes incluent l'annotation @Component .


ComposantL'annotation racine qui marque une classe comme candidate à l'implémentation automatique
ContrÎleurIndique que la classe est le contrÎleur pour envoyer des données vers l'avant.
@RestControllerIndique que la classe est le contrĂŽleur pour REST.
Contient des annotations Controller et @ResponseBody
Le serviceIndique que la classe est un service pour exécuter la logique métier.
DépÎtIndique que la classe est un référentiel pour travailler avec la base de données.
@ConfigurationIndique que la classe contient une configuration Java (méthodes @ Bean)

Quelles sont les portées bin? Quelle est leur visibilité par défaut?

Portée - portée. Il existe 2 étendues par défaut.


Singleton
La portée par défaut. Il n'y a qu'une seule instance de bean dans le conteneur
Prototype
Un nombre quelconque d'instances de bac peut ĂȘtre dans le conteneur

Et 4 Ă©tendues dans une application Web.


Demande
PortĂ©e - 1 requĂȘte HTTP. Un nouveau bean est crĂ©Ă© pour chaque requĂȘte.
SĂ©ance
Portée - 1 session. Un nouveau bean est créé pour chaque session.
Candidature
Portée - Cycle de vie ServletContext
Prise Web
Portée - Cycle de vie WebSocket

La portée est indiquée à l'aide de l'annotation @Bean sur les méthodes @Bean .


Quel est le lien entre les différents champs d'application et le multithreading?

La portĂ©e du prototype n'est pas sĂ»re pour les threads car cela ne garantit pas que la mĂȘme instance sera appelĂ©e uniquement dans 1 thread.


Par contre, Singleton Scope est thread-safe.


Comment les haricots sont-ils créés: instantanément ou paresseusement? Comment changer ce comportement?

Les beans singleton sont généralement créés immédiatement aprÚs l'analyse.
Les beans prototypes sont généralement créés uniquement sur demande.


Vous pouvez utiliser l'annotation @Lazy pour indiquer comment initialiser.
Il est placé sur les méthodes @ Bean, sur les classes @ Configuration ou sur les classes @ Component.
Selon le paramÚtre (vrai ou faux) accepté par l'annotation, l'initialisation sera paresseuse ou se fera immédiatement. Par défaut (c'est-à-dire sans spécifier de paramÚtre), true est utilisé.


Que se passe-t-il si un bac avec une étendue est intégré dans un bac avec une autre étendue?

Le bean singleton peut ĂȘtre intĂ©grĂ© Ă  n'importe quel autre bean.


Seul le prototype ou le singleton peut ĂȘtre intĂ©grĂ© au singleton .
Si vous implémentez un prototype, un prototype unique sera créé pour chaque singleton.


Le prototype peut ĂȘtre une dĂ©pendance pour n'importe quel bean.
Vous ne pouvez implémenter que singleton ou prototype.


Qu'est-ce qu'un BeanFactoryPostProcessor et quand est-il utilisé?
  • BeanFactoryPostProcessor fonctionne sur les descriptions de BeanFactoryPostProcessor ou les mĂ©tadonnĂ©es de configuration avant la crĂ©ation du bac.
  • Spring fournit plusieurs implĂ©mentations BeanFactoryPostProcessor utiles, par exemple, en lisant des fichiers de propriĂ©tĂ©s et en obtenant des propriĂ©tĂ©s de BeanFactoryPostProcessor .
  • Vous pouvez Ă©crire votre propre implĂ©mentation de BFPP.

Pourquoi avez-vous besoin de la méthode static @ Bean?

Afin d'utiliser BFPP personnalisé. Vous pouvez remplacer le mécanisme d'obtention des données à partir des métafichiers.


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

Décrire les propriétés de l'annotation @Bean
  • destroyMethod - pointe vers une mĂ©thode de rappel. La mĂ©thode est dans le bac.
  • initMethod - pointe vers une mĂ©thode de rappel. La mĂ©thode est dans le bac.
  • name - le nom du bean. Par dĂ©faut, le nom du bean est le nom de la mĂ©thode.
  • value - alias pour nom ()

Qu'est-ce qu'un BeanPostProcessor et en quoi est-il différent d'un BeanFactoryPostProcessor?

Spring utilise plusieurs BeanPostProcessors.
Par exemple, CommonAnnotationPostProcessor ou AutowiredAnnotationBeanPostProcessor .
BPP fonctionne avec les instances de bean, c'est-à-dire le conteneur crée le bac, puis BPP démarre.



Quelles sont les méthodes de rappel et comment les utiliser?

Il existe 3 options pour créer de telles méthodes:


  • @PreDestroy et @PostConstruct
  • Les destroyMethod initMethod et destroyMethod dans l'annotation destroyMethod qui pointent vers des mĂ©thodes de la classe bean
  • InitializingBean#afterPropertiesSet() et DisposableBean#destroy() . Pour remplacer ces mĂ©thodes, vous devez implĂ©menter les interfaces correspondantes.


Comment puis-je utiliser l'annotation @Autowire et quelle est la différence entre les façons?

Voici les types d'ID pouvant ĂȘtre utilisĂ©s dans votre application:


  • Constructeur DI
  • Setter di
  • Champ di

DI via le constructeur est considéré comme le meilleur moyen, car pour lui, il n'est pas nécessaire d'utiliser la réflexion, et il n'a pas non plus les inconvénients de DI à travers le passeur.
DI à travers le champ n'est pas recommandé, car Pour cela, une réflexion est utilisée qui réduit la productivité.
DI via le constructeur peut conduire à des dépendances circulaires . Pour éviter cela, vous pouvez utiliser l'initialisation paresseuse des beans ou DI via le setter.


DĂ©crire le comportement de l'annotation @Autowired
  1. Le conteneur détermine le type d'objet à incorporer.
  2. Un conteneur recherche des beans dans un contexte (aka un conteneur) qui correspond au type souhaité
  3. S'il y a plusieurs candidats et que l'un d'eux est marqué comme @Primary , alors il est implémenté
  4. Si des annotations @Autowire + Qualifier sont utilisées, le conteneur utilisera les informations de @Qualifier pour déterminer quel composant déployer
  5. Sinon, le conteneur tentera d'injecter le composant en fonction de son nom ou de son ID.
  6. Si aucune des méthodes n'a fonctionné, une exception sera levée

Le conteneur gĂšre l' ID Ă  l' aide d'un AutowiredAnnotationBeanPostProcessor . À cet Ă©gard, l'annotation ne peut ĂȘtre utilisĂ©e dans aucun BeanFactoryPP ou BeanPP.


Si l'objet injecté est un tableau, une collection ou une carte avec un générique, Spring incorporera tous les beans de type dans ce tableau (ou une autre structure de données). Dans le cas de la carte, la clé sera le nom du bean.


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

Comment faire de l'ID dans un domaine privé?

Vous pouvez utiliser différents types d'implémentation:


  • Constructeur
  • Setter
  • Injection sur le terrain
  • Valeur

Comment l'utilisation de @Qualifier complĂšte-t-elle @Autowired?

Spring fournit une annotation Qualifier pour surmonter le problÚme d'ambiguïté DI.


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

Si le conteneur a plusieurs cases du mĂȘme type (SomeClass), alors le conteneur implĂ©mentera exactement cette case, au-dessus de la mĂ©thode @ Bean dont il existe un qualificatif appropriĂ©. Vous ne pouvez pas non plus mettre de qualificatif sur une mĂ©thode, mais utiliser le nom du bean comme paramĂštre de qualificatif.
Le nom du bean peut ĂȘtre spĂ©cifiĂ© via le paramĂštre d'annotation Bean , et par dĂ©faut c'est le nom de la mĂ©thode d'usine.


Que sont les objets proxy et quels types d'objets proxy Spring peut-il créer?

Un proxy est un objet spĂ©cial qui a les mĂȘmes mĂ©thodes publiques que le bean, mais qui a des fonctionnalitĂ©s supplĂ©mentaires.
Deux types de procurations:


  • JDK-proxy - proxy dynamique. Les API sont intĂ©grĂ©es au JDK. Il a besoin d'une interface
  • Proxy CGLib - non intĂ©grĂ© au JDK. UtilisĂ© lorsque l'interface d'un objet n'est pas disponible.

Avantages des objets proxy:


  • Laisser ajouter un supplĂ©ment. logique - gestion des transactions, sĂ©curitĂ©, journalisation
  • SĂ©pare du code (journalisation, etc.) de la logique principale

Comment un bean singleton est-il implémenté?

S'il n'y a pas d'instance de bean dans le conteneur, la méthode @ Bean est appelée. S'il existe une instance de bean, le bean déjà créé est renvoyé.


Quels sont les profils? Quelles sont leurs raisons d'utiliser?

Lorsque vous utilisez la configuration Java, vous pouvez utiliser l'annotation @Profile .
Il vous permet d'utiliser différents paramÚtres pour Spring, en fonction du profil spécifié.
Il peut ĂȘtre placĂ© sur les classes @Configuration et Component , ainsi que sur les mĂ©thodes Bean .


 Profile("!test") //   ,   

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

Comment intégrer des valeurs simples dans des propriétés au printemps?

Vous pouvez utiliser l'annotation @Value pour @Value .
Ces valeurs peuvent ĂȘtre obtenues Ă  partir de fichiers de propriĂ©tĂ©s, de bacs, etc.


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

Une chaßne sera incorporée dans cette variable, par exemple, à partir d'une propriété ou d'une vue.


Comme d'habitude, veuillez envoyer les corrections ou les erreurs trouvées dans PM.

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


All Articles