Maison > Java > javaDidacticiel > le corps du texte

Analyse du code source Spring en Java

WBOY
Libérer: 2023-04-30 23:13:05
avant
820 Les gens l'ont consulté

Analyse du code source

1. Préparation précoce

<code>/**<br> * spring debug<br> * @author huangfu<br> */<br>public class SpringDebug {<br>public static void main(String[] args) {<br>		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(SpringDebugConfig.class);<br>	}<br>}<br></code>
Copier après la connexion

J'estime que la ligne de code ci-dessus est très familière à tous ceux qui ont utilisé Spring. Sinon, je vous conseille d'apprendre d'abord à l'utiliser. , puis plongez dans du code source La logique sous-jacente !

Voyons comment il instancie le bean étape par étape, prend le contrôle du bean, puis exécute diverses classes de cycle de vie ! Commençons par deviner. Lorsque Spring lit ces beans, les informations sur les beans doivent être stockées sur une certaine entité. Alors, quelle est cette entité ? Cette classe est BeanDefinition, alors que stocke-t-elle ? Jetons un coup d'œil à sa sous-classe AbstractBeanDefinitionBeanDefinition那么他存储了什么东西呢?我们看一下它的子类AbstractBeanDefinition

Analyse du code source Spring en Java        

里面定义这类似与这样的属性值,当然作者做截取了少数属性,它里面的属性远远比这多得多,它的目的就是bean实例化的时候,需要的数据不需要再通过自己去反射获取,而是再Spring初始化的时候全部读取,需要的时候从这里面拿就行,了解了bd的概念之后,我们是否疑惑?他读取之后存放在哪里呢?答案是存放再beanFactory里面,所以Spring初始化的时候肯定会先实现一个bean工厂!进入到AnnotationConfigApplicationContext里面,你会发下并没有初始化,在那初始化呢?众所周知,一个类再初始化的时候会先加载父类的构造函数,所以我们需要去看一下它的父类GenericApplicationContext:

<code>public GenericApplicationContext() {<br>    //初始化bean的工厂<br>    this.beanFactory = new DefaultListableBeanFactory();<br>}</code>     
Copier après la connexion

果然不出我所料,它再父类里面创建了bean工厂,工厂有了,我们继续回到AnnotationConfigApplicationContext里面往下看:发现它调用了一个this(),说明它调用了自己的空构造方法,所以,我们进入看一下:

<code>public AnnotationConfigApplicationContext() {<br>    //初始化读取器<br>    this.reader = new AnnotatedBeanDefinitionReader(this);<br>    //初始化扫描器<br>    this.scanner = new ClassPathBeanDefinitionScanner(this);<br>}</code>   
Copier après la connexion

「至此我们就可以看对照上面那幅图:初始化的时候bean工厂有了」

Analyse du code source Spring en Java        

「然后再自己的空构造方法里面有初始化了读取器!」

Analyse du code source Spring en Java        

那我们继续回到AnnotationConfigApplicationContext构造方法里面:

<code>   /**<br>	 * 创建一个新的AnnotationConfigApplicationContext,从给定的带注释的类派生bean定义<br>	 * 并自动刷新上下文。<br>	 * @param annotatedClasses one or more annotated classes,<br>	 * e.g. {@link Configuration @Configuration} classes<br>	 */<br>public AnnotationConfigApplicationContext(Class>... annotatedClasses) {<br>//读取Spring内置的几个的class文件转换为bd  然后初始化bean工厂<br>this();<br>//这一步就是将配置类Config进行了注册并解析bd<br>		register(annotatedClasses);<br>//这一步是核心,Spring的理解全在这一步,这一步理解了也就可以说将Spring理解了70%<br>//内部做一系列的操作如调用bean工厂的后置处理器   实例化类  调用 后置处理器的前置处理   初始化类  调用后置处理器的后置处理 注册事件监听等操作<br>//完成一个类从class文件变为bean的生命周期<br>		refresh();<br>	}</code>     
Copier après la connexion

下一步是调用register方法,干什么呢?试想一下,有时候我们的自动扫描配置是通过注解@ComponentScan("com.service")来配置的,这个类一般在哪?对了,一般实在配置类中的!

<code>@Configuration<br>@ComponentScan("com.service")<br>public class SpringDebugConfig {}</code>     
Copier après la connexion

为了能够知道,我们要扫描那些包下的类,我们就必须先去解析配置类的BeanDefinition,这样才能获取后续咱们要解析的包,当然这个方法不光解析了扫描的包,还解析了其他东西,本文不做讲解!     

2.核心功能

好了,再往下走我们就知道了我们即将要扫描那些包下的类,让他变成bean,那么我们继续向下走,走到refresh();

Analyse du code source Spring en Java

Il définit des valeurs d'attribut similaires à celle-ci. Bien sûr, l'auteur a intercepté quelques attributs, et il y a bien plus d'attributs Bien plus que cela, son objectif est que lorsque le bean est instancié, les données requises n'ont plus besoin d'être obtenues par réflexion, mais sont lues tout au long de l'initialisation de Spring. Il suffit de les prendre à partir d'ici lorsque cela est nécessaire. bd Après, on se le demande ? Où le stocke-t-il après l’avoir lu ? La réponse est de le stocker dans beanFactory, donc Spring implémentera certainement d'abord une bean factory lors de l'initialisation ! En entrant AnnotationConfigApplicationContext, vous constaterez qu'il n'a pas été initialisé. Où l'initialiser ? Comme nous le savons tous, lorsqu'une classe est réinitialisée, le constructeur de la classe parent sera chargé en premier, nous devons donc jeter un œil à sa classe parent GenericApplicationContext:

rrreee

Comme prévu, c'est la classe parent. La fabrique du bean est créée à l'intérieur, et la fabrique est là. Nous continuons à revenir à AnnotationConfigApplicationContext et regardons vers le bas : nous constatons qu'elle appelle un this(), indiquant qu'elle appelle. son propre constructeur vide, nous entrons donc Jetez un œil :
rrreee
"À ce stade, nous pouvons regarder l'image ci-dessus : la bean factory est là lors de l'initialisation"
Analyse du code source Spring en Java

"Puis vider Le lecteur est initialisé dans la méthode de construction ! 》

2. Fonctions de base

D'accord, si nous allons plus loin, nous saurons que nous sommes sur le point d'analyser les classes sous ces packages et de les transformer en beans, puis nous continuerons à descendre et à aller à refresh(). ;Cette méthode est incroyable. C'est la méthode de base de toute l'initialisation de Springbean. Si vous la comprenez, vous pourrez comprendre l'instanciation, les rappels et d'autres problèmes de Spring :
. Après notre arrivée, nous avons une méthode Pour analyser les fonctions qu'une méthode remplit, la première est :
1). de l'usine Spring créée précédemment est vide, cette méthode consiste à effectuer une série d'opérations de valeur d'initialisation pour lui !                                                   ' ' s ' s 1 donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc donc... Elle n'est actualisée qu'une seule fois et les erreurs sont signalées plusieurs fois. La fabrique de beans actuellement utilisée est renvoyée. Lorsque l'étape est XML, une nouvelle fabrique est renvoyée. créé et renvoyé. Conteneur Bean, enregistrez certains de ses propres post-processeurs Bean intégrés dans beanFactory, qui est généralement appelé BeanPostProcessor. Cette méthode est en fait une usine de réinitialisation !❞                                                                                 postProcessBeanFactory(beanFactory); Cela signifie que les développeurs Spring souhaitent que l'appelant l'utilise lors de la personnalisation de l'extension ! N i i). InvokebeanFactoryPostProcessors (Beanfactory);
croit en fait que le nom, la plupart des lecteurs peuvent deviner que son objectif est d'analyser l'enregistrement BD des classes non configurées dans l'usine pour tous les BeanFactoryPostProcessorscode>, le premier point d'extension apparaît ici. Lors de la personnalisation de <code>BeanFactoryPostProcessors, son timing de rappel correspond au moment où Spring lit tout ce que BeanDefinition est appelé ultérieurement. Les lecteurs peuvent se référer à Baidu pour des méthodes d'utilisation spécifiques. !

❞                                                                              registerBeanPostProcessors(beanFactory);                                                                                                                                                                   registerBeanPostProcessors(beanFactory); Enregistrez le processeur dans la fabrique de bean ! Je me demande si vous avez utilisé le point d'extension de l'interface beanPostProcessor ? Il est enregistré dans l'usine Spring selon cette méthode. Bien sûr, veuillez noter qu'il est uniquement enregistré et non exécuté ! N'oubliez pas et ne le faites pas !

❞                                                            initialisation des ressources
8) .initapplicationEventMulticaster ();

BeanFactoryPostProcessors,这里出现了第一个扩展点,自定义实现BeanFactoryPostProcessors的时候,他的回调时机是在Spring读取了全部的BeanDefinition之后调用的,具体的使用方法读者自行百度!

❞             
6). registerBeanPostProcessors(beanFactory);
❝      

这里是注册bean的后置处理器 也就是  beanPostProcessor 的实现 还有自己内置的处理器  注意这里并没有调用该处理器,只是将胡处理器注册进来bean工厂! 不知道大家使用过beanPostProcessor接口这个扩展点吗?他就是再这个方法里面被注册到Spring工厂里面的,当然注意一下,他只是注册进去了,并没有执行!记住并没有执行!

❞            
7). initMessageSource();
❝      

怎么说呢,这个方法作者并不准备深究,因为他和本篇文章的意图相违背,他的目的是做一个国际化操作也就是 i18n的资源初始化

❞             
8).initApplicationEventMulticaster();
❝      

Spring为我们提供了对于事件编程的封装,一般来说事件分为三个角色,事件广播器(发布事件),事件监听器(监听事件),事件源(具体的事件信息)三个角色,这个方法的目的就是初始化事件的广播器!

❞             
9). onRefresh();
❝      

这里又是一个扩展点,内部的方法为空,Spring并没有实现它,供调用者实现!

❞             
10). registerListeners();
❝      

注册Spring的事件监听器,上面已经说过了,这里是初始化并且注册事件监听器

❞             
11). finishBeanFactoryInitialization(beanFactory);
❝      

这个方法是一个重点,他是为了实例化所有剩余的(非延迟初始化)单例。我们所说的bean的实例化,注入,解决循环依赖,回调beanPostProcessor

的 的 的 的 的 的 的 的 的 的 的 est encapsulé pour la programmation d'événements De manière générale, les événements. sont divisés en trois rôles. Publication d'événements), Écouteur d'événements (écoute des événements), Source d'événement (informations spécifiques sur l'événement) trois rôles. le diffuseur de l'événement ! Sur 9). Onrefresh ();

Voici un autre point d'expansion. Spring ne s'en rend pas compte, et le fournisseur est réalisé !
❞                                                                                  registerListeners(); Cette méthode est un point important, elle consiste à instancier tous les singletons restants (initialisation non paresseuse). Ce que nous appelons l'instanciation du bean, l'injection, la résolution des dépendances circulaires, le rappel beanPostProcessor et d'autres opérations sont tous implémentés ici ! ❞                                                                                                                                                              . Les événements intégrés du printemps ❞ 🎜🎜🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal