Tout d'abord, le processus de base du démarrage de Tomcat
Je vous ai présenté la conception du cycle de vie dans Tomcat.Maîtriser cela nous est très utile pour analyser le processus de base de Tomcat, c'est-à-dire que nous devons créer des composants de base connexes, tels que Server et Service.cycle method.
1. Commencez la saisie
Vous pouvez démarrer le service Tomcat via un script (startup.bat), mais si vous regardez les commandes du script, vous constaterez que la méthode principale dans Bootstrap est finalement appelée, nous devons donc commencer par la méthode principale
Ensuite, nous regardons le code dans la méthode principale, il y a trois méthodes sur lesquelles nous devons nous concentrer
- méthode bootstrap.init()
- méthode load()
- méthode start()
C'est-à-dire que les opérations de base de Tomcat seront effectuées dans ces trois méthodes.
2. méthode d'initialisation
Jetons un coup d'œil au code dans la méthode init, nous supprimons simplement ceux qui ne sont pas essentiels
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;
}
复制代码
- La première consiste à appeler la méthode initClassLoaders(). Cette méthode terminera la création du ClassLoader correspondant. Ceci est plus important. J'écrirai un article pour le présenter plus tard.
- Créer un objet de classe Catalina par réflexion et créer une instance de Catalina par réflexion
- La relation parent-enfant du chargeur de classe est définie
- Utilisation de la variable de membre catalinaDaemon pour enregistrer l'instance de Catalina que nous avons créée
Ce sont des informations utiles que nous pouvons obtenir via la méthode bootstrap.init(). Ensuite, nous continuons à regarder ci-dessous.
3. méthode de chargement
Voyons ensuite ce que fait la méthode load. Le code est le suivant :
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);
}
复制代码
Le code ci-dessus est très simple, et nous pouvons également voir que la fonction de cette méthode est d'appeler la méthode load de Catalina en commentant. Nous devons donc également l'ajouter à la méthode de chargement de Catalina pour afficher, le code est également relativement long, ne laissant que le code clé
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操作
}
复制代码
Après avoir simplifié le code ci-dessus, nous constatons que la méthode Load est en fait assez simple et qu'elle fait deux choses.
- L'analyse du fichier Server.xml est réalisée via le composant Digester sous Apache
- L'initialisation des composants principaux tels que Server, Service, Engin et Connector est effectuée via la méthode getServer().init(), qui fait écho à la précédente LifecycleBase.
Si le contenu du cycle de vie n'est pas clair, veuillez consulter l'introduction de contenu précédente
4. méthode de démarrage
Enfin, regardons le code de la méthode start.
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);
}
复制代码
La logique du code ci-dessus est également très claire, c'est-à-dire que la méthode start de l'objet Catalina est appelée par réflexion. Allez donc à la méthode de démarrage de Catalina pour vérifier.
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();
}
}
复制代码
Grâce au code ci-dessus, nous pouvons constater que le code principal est toujours la méthode getServer.start(), c'est-à-dire que la méthode de démarrage de l'annotation associée est appelée imbriquée via l'objet Server.
5. Résumé du processus de base
Nous pouvons résumer le processus de base du démarrage de Tomcat à travers la figure suivante
D'après la figure, nous pouvons voir que Bootstrap ne fait pas réellement les choses essentielles, et c'est principalement fait par Catalina.
Travailler ensemble pour créer et grandir ensemble ! C'est le 20ème jour de ma participation au "Nuggets Daily New Plan · August Update Challenge", cliquez pour voir les détails de l'événement .