Maison >Java >javaDidacticiel >Analyse du code source Spring en Java
<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>
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 AbstractBeanDefinition
BeanDefinition
那么他存储了什么东西呢?我们看一下它的子类AbstractBeanDefinition
里面定义这类似与这样的属性值,当然作者做截取了少数属性,它里面的属性远远比这多得多,它的目的就是bean实例化的时候,需要的数据不需要再通过自己去反射获取,而是再Spring初始化的时候全部读取,需要的时候从这里面拿就行,了解了bd的概念之后,我们是否疑惑?他读取之后存放在哪里呢?答案是存放再beanFactory里面,所以Spring初始化的时候肯定会先实现一个bean工厂!进入到AnnotationConfigApplicationContext
里面,你会发下并没有初始化,在那初始化呢?众所周知,一个类再初始化的时候会先加载父类的构造函数,所以我们需要去看一下它的父类GenericApplicationContext
:
<code>public GenericApplicationContext() {<br> //初始化bean的工厂<br> this.beanFactory = new DefaultListableBeanFactory();<br>}</code>
果然不出我所料,它再父类里面创建了bean工厂,工厂有了,我们继续回到AnnotationConfigApplicationContext
里面往下看:发现它调用了一个this(),说明它调用了自己的空构造方法,所以,我们进入看一下:
<code>public AnnotationConfigApplicationContext() {<br> //初始化读取器<br> this.reader = new AnnotatedBeanDefinitionReader(this);<br> //初始化扫描器<br> this.scanner = new ClassPathBeanDefinitionScanner(this);<br>}</code>
「至此我们就可以看对照上面那幅图:初始化的时候bean工厂有了」
「然后再自己的空构造方法里面有初始化了读取器!」
那我们继续回到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>
下一步是调用register
方法,干什么呢?试想一下,有时候我们的自动扫描配置是通过注解@ComponentScan("com.service")
来配置的,这个类一般在哪?对了,一般实在配置类中的!
<code>@Configuration<br>@ComponentScan("com.service")<br>public class SpringDebugConfig {}</code>
为了能够知道,我们要扫描那些包下的类,我们就必须先去解析配置类的BeanDefinition
,这样才能获取后续咱们要解析的包,当然这个方法不光解析了扫描的包,还解析了其他东西,本文不做讲解!
好了,再往下走我们就知道了我们即将要扫描那些包下的类,让他变成bean,那么我们继续向下走,走到refresh();
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 : "Puis vider Le lecteur est initialisé dans la méthode de construction ! 》
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 lesBeanFactoryPostProcessorscode>, 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 queBeanDefinition
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
❞ initialisation des ressourcesbeanPostProcessor
? 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 !
❞
BeanFactoryPostProcessors
,这里出现了第一个扩展点,自定义实现BeanFactoryPostProcessors
的时候,他的回调时机是在Spring读取了全部的BeanDefinition
之后调用的,具体的使用方法读者自行百度!
❝这里是注册bean的后置处理器 也就是 beanPostProcessor 的实现 还有自己内置的处理器 注意这里并没有调用该处理器,只是将胡处理器注册进来bean工厂! 不知道大家使用过
❞beanPostProcessor
接口这个扩展点吗?他就是再这个方法里面被注册到Spring工厂里面的,当然注意一下,他只是注册进去了,并没有执行!记住并没有执行!
❝怎么说呢,这个方法作者并不准备深究,因为他和本篇文章的意图相违背,他的目的是做一个国际化操作也就是 i18n的资源初始化
❞
❝Spring为我们提供了对于事件编程的封装,一般来说事件分为三个角色,
❞事件广播器
(发布事件),事件监听器
(监听事件),事件源
(具体的事件信息)三个角色,这个方法的目的就是初始化事件的广播器!
❝这里又是一个扩展点,内部的方法为空,Spring并没有实现它,供调用者实现!
❞
❝注册Spring的事件监听器,上面已经说过了,这里是初始化并且注册事件监听器
❞
❝这个方法是一个重点,他是为了实例化所有剩余的(非延迟初始化)单例。我们所说的bean的实例化,注入,解决循环依赖,回调
beanPostProcessor
É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 (); ❞ 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❝
Voici un autre point d'expansion. Spring ne s'en rend pas compte, et le fournisseur est réalisé !
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!