JavaRush /Blog Java /Random-FR /Cadre de printemps. Introduction
Marchello
Niveau 20
Санкт-Петербург

Cadre de printemps. Introduction

Publié dans le groupe Random-FR
Bonjour! Alors que l'administration JavaRush travaille à de nouveaux niveaux, je souhaite lancer une série d'articles de formation sur Spring Framework. Oui, je sais qu'il existe déjà beaucoup de matériel sur ce sujet sur Internet, mais, comme le montre la pratique, ils sont tous au niveau Hello World. Je veux parler non pas de la façon de placer correctement les annotations, mais de la façon dont tout cela fonctionne « sous le capot ». L'article est destiné à ceux qui ont déjà travaillé avec ce framework d'une manière ou d'une autre et qui connaissent les concepts de base. Cadre de printemps.  Présentation - 1

Initialisation du contexte.

Alors commençons par les bases. À mon avis, l’un des points les plus importants est de comprendre comment le contexte est configuré et comment les beans sont initialisés. Comme vous le savez, avant que Spring ne commence à fonctionner, il doit être configuré. À l'époque antédiluvienne, cela se faisait à l'aide de fichiers XML (sur certains projets, principalement les plus anciens, ils continuent de le faire aujourd'hui). Voici un petit exemple d'un tel fichier de configuration :
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

   <bean id="helloWorld" class="ru.javarush.HelloWorld">
       <property name="message" value="Hello World!"/>
   </bean>

</beans>
En gros, cela suffit pour créer quelques contrôleurs et lancer une startup (qui ne décollera pas). Mais comment cette configuration fera-t-elle fonctionner Spring ? Et c'est ici que les choses deviennent intéressantes. Pour que notre configuration soit comprise par Spring, il existe un fichier XmlBeanDefinitionReader. BeanDefinitionIl s'agit d'un composant interne de Spring qui analyse (analyse) XML et crée des fichiers basés sur ce que nous avons écrit ici . BeanDefinitionest un objet qui stocke des informations sur le bean. Cela inclut : à partir de quelle classe il (le bean) doit être créé ; portée; si l'initialisation paresseuse est installée ; Est-il nécessaire d'initialiser avant ce bean une autre propriété et d'autres propriétés décrites en XML. Tous les reçus BeanDefinitionsont ajoutés à HashMap, dans lequel l'identifiant est le nom du bean (défini par vous ou attribué par Spring) et BeanDefinitionl'objet lui-même. Une fois que tout BeanDefinitionest créé, un nouveau héros apparaît sur scène - BeanFactory. Cet objet parcourt HashMap’es BeanDefinition, crée des beans basés sur eux et les place dans un conteneur IoC. Il y a une nuance ici, en fait, au démarrage de l'application, le conteneur IoC contiendra des beans qui ont une portée Singleton (définie par défaut), tandis que les autres sont créés lorsqu'ils sont nécessaires (prototype, requête, session). Et maintenant une petite digression, faisons connaissance avec un autre personnage.

Découvrez BeanPostProcessor. (BPP)

post-processeur de haricotsLe fait est qu’un bean n’est pas nécessairement une classe de logique métier pour votre application. Un bean est également appelé bean d'infrastructure. En bref, un bean d'infrastructure est une classe qui configure vos beans de logique métier (oui, trop de beans). Je vais vous en dire plus ci-dessous, mais pour que ce soit un peu plus clair sur ce que BPP configure exactement, je vais donner un exemple. Est-ce que tout le monde connaît le résumé @Autowired? Vous êtes donc AutowiredAnnotationBeanPostProcessorresponsable de vous assurer que tous vos cours sont intégrés les uns aux autres. je sais que je veux dire

Revenons à BeanFactory

Connaissant maintenant BPP, vous devez préciser que lors d'une itération sur HashMaples , BeanDefinitiontous les ' sont d'abord créés et placés séparément (pas dans le conteneur IoC) BeanPostProcessor. Après cela, les beans réguliers de notre logique métier sont créés, placés dans un conteneur IoC, et leur configuration commence à l'aide de BPP différés séparément. Et voilà comment ça se passe, chaque BPP a 2 méthodes :
postProcessorBeforeInitialization(Object bean, String beanName);
postProcessorAfterInitialization(Object bean, String beanName);
Parcourt nos bacs deux fois. La première fois que la méthode est appelée postProcessorBeforeInitialization, et la deuxième fois, la méthode est appelée postProcessorAfterInitialization. La question s'est sûrement posée de savoir pourquoi deux méthodes sont nécessaires, permettez-moi de vous expliquer. Le fait est que pour traiter certaines annotations (comme @Transactional, par exemple), notre bean est remplacé par une classe proxy. Pour comprendre pourquoi cela se fait, vous devez savoir comment cela fonctionne @Transactional, et voici comment cela fonctionne. Vous devez ajouter quelques lignes de code supplémentaires à la méthode marquée de cette annotation à la volée. Comment faire? C'est vrai, en créant une classe proxy, à l'intérieur de laquelle le code nécessaire sera ajouté à la méthode requise. Imaginez maintenant cette situation, nous avons une classe :
class A {
    @Autowired
    private SomeClass someClass;

    @Transactional
    public void method() {
        // модификатор доступа обязательно public
    }
}
Cette classe a 2 annotations @Autowiredet @Transactional. Les deux annotations sont traitées par des BPP différents. Si cela fonctionne en premier AutowiredBPP, alors tout ira bien, mais sinon, nous rencontrerons ce problème. Le fait est que lors de la création d’une classe proxy, toutes les méta-informations sont perdues. En d'autres termes, il n'y aura aucune information sur l'annotation @Autowireddans la classe proxy, et donc AutowiredBPPcela ne fonctionnera pas, ce qui signifie que notre champ someClassaura la valeur null, ce qui conduira très probablement à un NPE. Il faut également savoir qu'entre les appels de méthode, la -method postProcessorBeforeInitializationest postProcessorAfterInitializationappelée init, s'il y en a une. Il s'agit essentiellement du deuxième constructeur, mais la différence est qu'à ce moment, toutes nos dépendances sont déjà intégrées dans la classe et nous pouvons y accéder à partir initde la méthode -. Donc, encore une fois l'algorithme d'initialisation du contexte :
  1. XmlBeanDefinitionReaderanalyse notre fichier de configuration XML.
  2. Crée BeanDefinitionles et les met dans HashMap.
  3. Vient BeanFactoryet à partir de cela HashMapadditionne séparément tous les BeanPostProcessor'.
  4. Crée BeanDefinitiondes beans à partir de et les place dans un conteneur IoC.
  5. Ici les BPP viennent configurer ces beans en utilisant 2 méthodes.
  6. Prêt.
En fait, c'est tout, écrivez si vous avez aimé l'article et si cela vaut la peine de continuer à écrire de tels tutoriels.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION