Zuerst der Kernprozess des Tomcat-Starts
Ich habe Ihnen das Design des Lebenszyklus in Tomcat vorgestellt. Diese zu beherrschen ist sehr hilfreich für uns, um den Kernprozess von Tomcat zu analysieren, d.h. wir müssen verwandte Kernkomponenten erstellen, wie z.
1. Starten Sie die Eingabe
Sie können den Tomcat-Dienst über ein Skript (startup.bat) starten, aber wenn Sie sich die Befehle des Skripts ansehen, werden Sie feststellen, dass die Hauptmethode in Bootstrap schließlich aufgerufen wird, sodass wir von der Hauptmethode ausgehen müssen
Dann schauen wir uns den Code in der Hauptmethode an, es gibt drei Methoden, auf die wir uns konzentrieren müssen
- bootstrap.init()-Methode
- load()-Methode
- start()-Methode
Das heißt, die Kernoperationen von Tomcat werden in diesen drei Methoden abgeschlossen.
2. init-Methode
Werfen wir einen Blick auf den Code in der Methode init, wir entfernen nur die nicht zum Kern gehörenden
public void init() throws Exception {
// 创建相关的类加载器
initClassLoaders();
// 省略部分代码...
// 通过反射创建了 Catalina 类对象
Class<?> startupClass = catalinaLoader
.loadClass("org.apache.catalina.startup.Catalina");
// 创建了 Catalina 实例
Object startupInstance = startupClass.getConstructor().newInstance();
// 省略部分代码...
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
// 把 sharedLoader 设置为了 commonLoader的父加载器
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
// Catalina 实例 赋值给了 catalinaDaemon
catalinaDaemon = startupInstance;
}
复制代码
- Die erste besteht darin, die Methode initClassLoaders() aufzurufen. Diese Methode wird die Erstellung des entsprechenden ClassLoaders abschließen. Das ist wichtiger. Ich werde später einen Artikel schreiben, um es vorzustellen.
- Erstellen Sie ein Catalina-Klassenobjekt durch Reflektion und erstellen Sie eine Instanz von Catalina durch Reflektion
- Die Eltern-Kind-Beziehung des Klassenladers ist eingestellt
- Die Member-Variable catalinaDaemon wurde verwendet, um die von uns erstellte Catalina-Instanz aufzuzeichnen
Dies sind nützliche Informationen, die wir über die Methode bootstrap.init() erhalten können. Dann schauen wir unten weiter.
3. Lademethode
Sehen wir uns dann an, was die load-Methode macht. Der Code lautet wie folgt:
private void load(String[] arguments) throws Exception {
// Call the load() method
String methodName = "load"; // load方法的名称
Object param[];
Class<?> paramTypes[];
if (arguments==null || arguments.length==0) {
paramTypes = null;
param = null;
} else {
paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
param = new Object[1];
param[0] = arguments;
}
// catalinaDaemon 就是在 init中创建的 Catalina 对象
Method method =
catalinaDaemon.getClass().getMethod(methodName, paramTypes);
if (log.isDebugEnabled()) {
log.debug("Calling startup class " + method);
}
// 会执行 Catalina的load方法
method.invoke(catalinaDaemon, param);
}
复制代码
Der obige Code ist sehr einfach, und wir können auch sehen, dass die Funktion dieser Methode darin besteht, die Lademethode von Catalina durch Kommentieren aufzurufen. Wir müssen es also auch zur Lademethode von Catalina hinzufügen, um anzuzeigen, dass der Code auch relativ lang ist und nur der Schlüsselcode übrig bleibt
public void load() {
if (loaded) {
return; // 只能被加载一次
}
loaded = true;
initDirs(); // 废弃的方法
// Before digester - it may be needed
initNaming(); // 和JNDI 相关的内容 忽略
// Create and execute our Digester
// 创建并且执行我们的 Digester 对象 Server.xml
Digester digester = createStartDigester();
// 省略掉了 Digester文件处理的代码
getServer().setCatalina(this); // Server对象绑定 Catalina对象
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
// Stream redirection
initStreams();
// 省略掉了部分代码...
getServer().init(); // 完成 Server Service Engine Connector等组件的init操作
}
复制代码
Nachdem wir den obigen Code vereinfacht haben, stellen wir fest, dass die Load-Methode eigentlich recht einfach ist und zwei Dinge tut.
- Die Analyse der Server.xml-Datei wird durch die Digester-Komponente unter Apache durchgeführt
- Die Initialisierung von Kernkomponenten wie Server, Service, Engin und Connector wird durch die getServer().init()-Methode abgeschlossen, die die vorherige LifecycleBase widerspiegelt.
Wenn der Inhalt des Lebenszyklus nicht klar ist, lesen Sie bitte die vorherige Inhaltseinführung
4. Startmethode
Schauen wir uns zum Schluss noch den Code der start-Methode an.
public void start() throws Exception {
if (catalinaDaemon == null) {
init(); // 如果 catalinaDaemon 为空 初始化操作
}
// 获取的是 Catalina 中的 start方法
Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
// 执行 Catalina 的start方法
method.invoke(catalinaDaemon, (Object [])null);
}
复制代码
Die Logik des obigen Codes ist auch sehr klar, das heißt, die Startmethode des Catalina-Objekts wird durch Reflektion aufgerufen. Gehen Sie also zur Startmethode von Catalina, um dies zu überprüfen.
public void start() {
if (getServer() == null) {
load(); // 如果Server 为空 重新 init 相关的组件
}
if (getServer() == null) {
log.fatal("Cannot start server. Server instance is not configured.");
return;
}
// Start the new server 关键方法--->启动Server
try {
getServer().start();
} catch (LifecycleException e) {
// 省略...
}
// 省略...
// Register shutdown hook 注册关闭的钩子
if (useShutdownHook) {
// 省略...
}
if (await) {
await();
stop();
}
}
复制代码
Durch den obigen Code können wir feststellen, dass der Kerncode immer noch die getServer.start()-Methode ist, d. h. die start-Methode der zugehörigen Anmerkung wird verschachtelt durch das Server-Objekt aufgerufen.
5. Zusammenfassung des Kernprozesses
Wir können den Kernprozess des Starts von Tomcat durch die folgende Abbildung zusammenfassen
Aus der Abbildung können wir ersehen, dass Bootstrap eigentlich nicht die Kernaufgaben erledigt, sondern hauptsächlich von Catalina erledigt wird.
Arbeiten Sie zusammen, um gemeinsam zu schaffen und zu wachsen! Dies ist der 20. Tag meiner Teilnahme an der „Nuggets Daily New Plan · August Update Challenge“, klicken Sie hier, um die Veranstaltungsdetails anzuzeigen .