Heim  >  Artikel  >  Java  >  Spring-Quellcode-Analyse in Java

Spring-Quellcode-Analyse in Java

WBOY
WBOYnach vorne
2023-04-30 23:13:05776Durchsuche

#? 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

Spring-Quellcode-Analyse in Java

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>     

"An diesem Punkt können wir uns das Bild ansehen oben: Die Bean-Factory ist während der Initialisierung da. 887/227/168286758998691.png" alt="Spring-Quellcode-Analyse in Java" / >

"Dann initialisieren Sie den Reader in Ihrer eigenen leeren Konstruktionsmethode!" #🎜 🎜#

Dann machen wir weiter. Gehen Sie zurück zum 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
Spring-Quellcode-Analyse in Java        

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

<code>@Configuration<br>@ComponentScan("com.service")<br>public class SpringDebugConfig {}</code>     

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

rrreee

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

Spring-Quellcode-Analyse in Java        

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

Spring-Quellcode-Analyse in Java        

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

rrreee

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

rrreee

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

2.核心功能

好了,再往下走我们就知道了我们即将要扫描那些包下的类,让他变成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

Okay, wenn wir weitermachen, wissen wir, dass wir dabei sind, die Klassen unter diesen Paketen zu scannen und in Bohnen umzuwandeln, also machen wir weiter Gehen Sie nach unten und gehen Sie zu 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). ;
# 🎜🎜#❝
Hier ist eine Reihe von Zuweisungsvorgängen vor dem Aktualisieren der Bean-Fabrik, hauptsächlich weil viele Eigenschaften der zuvor erstellten Spring-Fabrik leer sind. Diese Methode dient dazu, einige Initialisierungswertoperationen durchzuführen !
##🎜🎜 ## 🎜🎜#2). Die aktuelle Bean-Factory wird nur einmal aktualisiert, es werden mehrere Fehler gemeldet und die aktuell verwendete Bean-Factory wird zurückgegeben. Wenn der Schritt XML ist, wird eine neue Factory erstellt und zurückgegeben.❞                                                                 postProcessBeanFactory(beanFactory); Was bedeutet die leere Methode? Das bedeutet, dass Spring-Entwickler möchten, dass Aufrufer benutzerdefinierte Erweiterungen verwenden! N i i). >, der erste Erweiterungspunkt erscheint hier, wenn 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!
❞                                                     initMessageSource(); Ressourceninitialisierung
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).
❞                                                                                   registerListeners(); Initialization(beanFactory);
❝ ​

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之后调用的,具体的使用方法读者自行百度!

❞             
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❞                                                                                                                                                           . 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!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen