Heim >Java >javaLernprogramm >Spring-Quellcode-Analyse in Java
#? Ich schätze, dass jeder, der Spring verwendet hat, mit dem Code sehr vertraut ist. Wenn Sie damit nicht vertraut sind, empfehle ich Ihnen, zuerst die Verwendung zu erlernen und sich dann mit der zugrunde liegenden Logik des Quellcodes zu befassen!
Schauen wir uns an, wie er die Bean Schritt für Schritt instanziiert, die Bean übernimmt und dann verschiedene Lebenszyklusklassen ausführt! Lassen Sie uns zunächst eine Vermutung anstellen. Wenn Spring diese Bohnen liest, müssen die Informationen über die Bohnen auf einer bestimmten Entität gespeichert werden. Diese Klasse ist BeanDefinition
. Was speichert sie also? Werfen wir einen Blick auf die Unterklasse AbstractBeanDefinition
Es definiert Attributwerte ähnlich diesem. Natürlich hat der Autor einige Attribute abgefangen. Es gibt weit mehr Eigenschaften als diese. Der Zweck besteht darin, dass die erforderlichen Daten bei der Instanziierung nicht selbst durch Reflektion abgerufen werden müssen. Stattdessen können Sie sie bei der Spring-Initialisierung abrufen Sind wir verwirrt, nachdem wir das Konzept von bd verstanden haben? Wo wird es nach dem Lesen gespeichert? Die Antwort besteht darin, es in der beanFactory zu speichern, sodass Spring bei der Initialisierung auf jeden Fall zuerst eine Bean-Factory implementiert! Wenn Sie AnnotationConfigApplicationContext
eingeben, werden Sie feststellen, dass es nicht initialisiert wurde. Wo soll es initialisiert werden? Wie wir alle wissen, wird bei der Neuinitialisierung einer Klasse zuerst der Konstruktor der übergeordneten Klasse geladen, daher müssen wir einen Blick auf den GenericApplicationContext
der übergeordneten Klasse werfen:
<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># 🎜🎜# Tatsächlich ist es nicht das, was ich dachte. Den Informationen zufolge wird eine Bean-Factory in der übergeordneten Klasse erstellt. Da die Factory nun verfügbar ist, gehen wir zurück zu
AnnotationConfigApplicationContext
und schauen nach unten : Wir stellen fest, dass es ein this() aufruft, was darauf hinweist, dass es seine eigene leere Konstruktormethode aufruft, also werfen wir einen Blick darauf: <code>public GenericApplicationContext() {<br> //初始化bean的工厂<br> this.beanFactory = new DefaultListableBeanFactory();<br>}</code>
AnnotationConfigApplicationContext
-Konstruktor:
<code>public AnnotationConfigApplicationContext() {<br> //初始化读取器<br> this.reader = new AnnotatedBeanDefinitionReader(this);<br> //初始化扫描器<br> this.scanner = new ClassPathBeanDefinitionScanner(this);<br>}</code>Der nächste Schritt besteht darin, das
register-Methode. Was ist zu tun? Stellen Sie sich vor, manchmal wird unsere automatische Scankonfiguration über die Annotation <code>@ComponentScan("com.service")
konfiguriert. Wo befindet sich diese Klasse normalerweise? Normalerweise liegt es übrigens in der Konfigurationsklasse!
<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>
BeanDefinition
那么他存储了什么东西呢?我们看一下它的子类AbstractBeanDefinition
里面定义这类似与这样的属性值,当然作者做截取了少数属性,它里面的属性远远比这多得多,它的目的就是bean实例化的时候,需要的数据不需要再通过自己去反射获取,而是再Spring初始化的时候全部读取,需要的时候从这里面拿就行,了解了bd的概念之后,我们是否疑惑?他读取之后存放在哪里呢?答案是存放再beanFactory里面,所以Spring初始化的时候肯定会先实现一个bean工厂!进入到AnnotationConfigApplicationContext
里面,你会发下并没有初始化,在那初始化呢?众所周知,一个类再初始化的时候会先加载父类的构造函数,所以我们需要去看一下它的父类GenericApplicationContext
:
<code>@Configuration<br>@ComponentScan("com.service")<br>public class SpringDebugConfig {}</code>
果然不出我所料,它再父类里面创建了bean工厂,工厂有了,我们继续回到AnnotationConfigApplicationContext
里面往下看:发现它调用了一个this(),说明它调用了自己的空构造方法,所以,我们进入看一下:
「至此我们就可以看对照上面那幅图:初始化的时候bean工厂有了」
「然后再自己的空构造方法里面有初始化了读取器!」
那我们继续回到AnnotationConfigApplicationContext
构造方法里面:
下一步是调用register
方法,干什么呢?试想一下,有时候我们的自动扫描配置是通过注解@ComponentScan("com.service")
来配置的,这个类一般在哪?对了,一般实在配置类中的!
为了能够知道,我们要扫描那些包下的类,我们就必须先去解析配置类的BeanDefinition
,这样才能获取后续咱们要解析的包,当然这个方法不光解析了扫描的包,还解析了其他东西,本文不做讲解!
好了,再往下走我们就知道了我们即将要扫描那些包下的类,让他变成bean,那么我们继续向下走,走到refresh();
Um zu wissen, dass wir die Klassen unter diesen Paketen scannen möchten, müssen wir zuerst die BeanDefinition
der Konfigurationsklasse analysieren, damit wir die Pakete erhalten können, die wir benötigen Ich möchte es später analysieren. Natürlich analysiert diese Methode nicht nur die gescannten Pakete, sondern auch andere Dinge, die ich in diesem Artikel nicht erklären werde!
2. Kernfunktionen
refresh();
. Es ist die Kernmethode der gesamten Springbean-Initialisierung. Wenn Sie sie verstehen, werden Sie die Instanziierung, Rückrufe und andere Probleme verstehen . Wir gehen rein und werfen einen Blick darauf: Nachdem wir reingekommen sind, analysieren wir, welche Funktionen Methode für Methode ausgeführt werden: 1). ;# 🎜🎜#❝
BeanFactoryPostProcessors
angepasst wird, ist sein Rückrufzeitpunkt, wenn Spring alles liest BeanDefinition
wird später auf Baidu verwiesen. ❞ Registrieren Sie den Server in der Bean Factory! Haben Sie jemals den Erweiterungspunkt der beanPostProcessor
-Schnittstelle verwendet? Bei dieser Methode wird es in der Spring-Factory registriert. Bitte beachten Sie, dass es nur registriert und nicht ausgeführt wird! Erinnern funktioniert nicht! 8) .initApplicationEventMulticaster (); ❝Spring bietet uns eine Kapselung der Ereignisprogrammierung. Im Allgemeinen sind Ereignisse in drei Zeichen unterteilt:
Event Broades
(. Ereignisse veröffentlichen), Ereignis-Listener
(auf Ereignisse warten), Ereignisquelle
(spezifische Ereignisinformationen) drei Rollen Der Zweck dieser Methode besteht darin, den Ereignis-Broadcaster zu initialisieren! Zu 9). ❝ Diese Methode ist ein wichtiger Punkt: Sie dient dazu, alle verbleibenden Singletons (nicht verzögerte Initialisierung) zu instanziieren. Was wir Bean-Instanziierung, Injektion, Auflösung zirkulärer Abhängigkeiten, Rückruf
❞beanPostProcessor
und andere Operationen nennen, werden hier alle implementiert!BeanFactoryPostProcessors
,这里出现了第一个扩展点,自定义实现BeanFactoryPostProcessors
的时候,他的回调时机是在Spring读取了全部的BeanDefinition
之后调用的,具体的使用方法读者自行百度!
❝这里是注册bean的后置处理器 也就是 beanPostProcessor 的实现 还有自己内置的处理器 注意这里并没有调用该处理器,只是将胡处理器注册进来bean工厂! 不知道大家使用过
❞beanPostProcessor
接口这个扩展点吗?他就是再这个方法里面被注册到Spring工厂里面的,当然注意一下,他只是注册进去了,并没有执行!记住并没有执行!
❝怎么说呢,这个方法作者并不准备深究,因为他和本篇文章的意图相违背,他的目的是做一个国际化操作也就是 i18n的资源初始化
❞
❝Spring为我们提供了对于事件编程的封装,一般来说事件分为三个角色,
❞事件广播器
(发布事件),事件监听器
(监听事件),事件源
(具体的事件信息)三个角色,这个方法的目的就是初始化事件的广播器!
❝这里又是一个扩展点,内部的方法为空,Spring并没有实现它,供调用者实现!
❞
❝注册Spring的事件监听器,上面已经说过了,这里是初始化并且注册事件监听器
❞
❝这个方法是一个重点,他是为了实例化所有剩余的(非延迟初始化)单例。我们所说的bean的实例化,注入,解决循环依赖,回调
❞beanPostProcessor
❞ . Die integrierten Frühlingsereignisse
Das obige ist der detaillierte Inhalt vonSpring-Quellcode-Analyse in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!