Tomcat源码分析(二)Bootstrap启动类分析

目录
上一章,我们下载源码,并启动了源码,Tomcat源码分析(一)启动Tomcat源码
现在,我们来看看Bootstrap启动类做了些什么工作。

静态代码块

设置了catelina.home和catalina.base 
点击查看代码
static {     // Will always be non-null     // 当前工作目录的路径,总是不会为null     String userDir = System.getProperty(user.dir);      // Home first     String home = System.getProperty(Constants.CATALINA_HOME_PROP);     File homeFile = null;      if (home != null) {         File f = new File(home);         try {             homeFile = f.getCanonicalFile();         } catch (IOException ioe) {             homeFile = f.getAbsoluteFile();         }     }      if (homeFile == null) {         // First fall-back. See if current directory is a bin directory         // in a normal Tomcat install         File bootstrapJar = new File(userDir, bootstrap.jar);          if (bootstrapJar.exists()) {             File f = new File(userDir, ..);             try {                 homeFile = f.getCanonicalFile();             } catch (IOException ioe) {                 homeFile = f.getAbsoluteFile();             }         }     }      if (homeFile == null) {         // Second fall-back. Use current directory         File f = new File(userDir);         try {             homeFile = f.getCanonicalFile();         } catch (IOException ioe) {             homeFile = f.getAbsoluteFile();         }     }      catalinaHomeFile = homeFile;     // 设置了catelina.home     System.setProperty(Constants.CATALINA_HOME_PROP, catalinaHomeFile.getPath());      // Then base     String base = System.getProperty(Constants.CATALINA_BASE_PROP);     if (base == null) {         catalinaBaseFile = catalinaHomeFile;     } else {         File baseFile = new File(base);         try {             baseFile = baseFile.getCanonicalFile();         } catch (IOException ioe) {             baseFile = baseFile.getAbsoluteFile();         }         catalinaBaseFile = baseFile;     }     // 设置了catalina.base     System.setProperty(Constants.CATALINA_BASE_PROP, catalinaBaseFile.getPath()); } 

main()方法

1.加锁新建一个Bootstrap对象,调用init初始化并且赋值给了私有静态对象daemon 2.调用了daemon对象load和start方法,而load和start方法里面利用了反射调用了catalinaDeamon的load和start方法 
点击查看代码
/**  * Main method and entry point when starting Tomcat via the provided  * scripts.  *  * @param args Command line arguments to be processed  */ public static void main(String args[]) {      synchronized (daemonLock) {         if (daemon == null) {             // Don't set daemon until init() has completed             Bootstrap bootstrap = new Bootstrap();             try {                 bootstrap.init();             } catch (Throwable t) {                 handleThrowable(t);                 t.printStackTrace();                 return;             }             daemon = bootstrap;         } else {             // When running as a service the call to stop will be on a new             // thread so make sure the correct class loader is used to             // prevent a range of class not found exceptions.             Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);         }     }      try {         String command = start;         if (args.length > 0) {             command = args[args.length - 1];         }          if (command.equals(startd)) {             args[args.length - 1] = start;             daemon.load(args);             daemon.start();         } else if (command.equals(stopd)) {             args[args.length - 1] = stop;             daemon.stop();         } else if (command.equals(start)) {             daemon.setAwait(true);             daemon.load(args);             daemon.start();             if (null == daemon.getServer()) {                 System.exit(1);             }         } else if (command.equals(stop)) {             daemon.stopServer(args);         } else if (command.equals(configtest)) {             daemon.load(args);             if (null == daemon.getServer()) {                 System.exit(1);             }             System.exit(0);         } else {             log.warn(Bootstrap: command \ + command + \ does not exist.);         }     } catch (Throwable t) {         // Unwrap the Exception for clearer error reporting         if (t instanceof InvocationTargetException &&                 t.getCause() != null) {             t = t.getCause();         }         handleThrowable(t);         t.printStackTrace();         System.exit(1);     } } 

init()方法

1.使用initClassLoaders()创建了commonLoader、catalinaLoader和sharedLoader 2.利用反射新建一个org.apache.catalina.startup.Catalina类对象,赋值给了catalinaDeamon。 
点击查看代码
/**  * Initialize daemon.  * @throws Exception Fatal initialization error  */ public void init() throws Exception {      initClassLoaders();      Thread.currentThread().setContextClassLoader(catalinaLoader);      SecurityClassLoad.securityClassLoad(catalinaLoader);               // Load our startup class and call its process() method     // 加载启动类并调用其process()方法      if (log.isDebugEnabled()) {         log.debug(Loading startup class);     }     Class<?> startupClass = catalinaLoader.loadClass(org.apache.catalina.startup.Catalina);     Object startupInstance = startupClass.getConstructor().newInstance();      // Set the shared extensions class loader     if (log.isDebugEnabled()) {         log.debug(Setting startup class properties);     }            String methodName = setParentClassLoader;     Class<?> paramTypes[] = new Class[1];     paramTypes[0] = Class.forName(java.lang.ClassLoader);     Object paramValues[] = new Object[1];     paramValues[0] = sharedLoader;     Method method =         startupInstance.getClass().getMethod(methodName, paramTypes);     method.invoke(startupInstance, paramValues);      catalinaDaemon = startupInstance; } 

initClassLoaders()方法

创建了commonLoader、catalinaLoader和sharedLoader 
点击查看代码
private void initClassLoaders() {     try {         commonLoader = createClassLoader(common, null);         if (commonLoader == null) {             // no config file, default to this loader - we might be in a 'single' env.             commonLoader = this.getClass().getClassLoader();         }         catalinaLoader = createClassLoader(server, commonLoader);         sharedLoader = createClassLoader(shared, commonLoader);     } catch (Throwable t) {         handleThrowable(t);         log.error(Class loader creation threw exception, t);         System.exit(1);     } } 

load()方法

通过反射调用catalinaDaemon的load()方法 
点击查看代码
/**  * Load daemon.  */ private void load(String[] arguments) throws Exception {      // Call the load() method     String methodName = 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;     }     Method method =         catalinaDaemon.getClass().getMethod(methodName, paramTypes);     if (log.isDebugEnabled()) {         log.debug(Calling startup class  + method);     }     method.invoke(catalinaDaemon, param); } 

start()方法

 通过反射调用catalinaDaemon的start()方法 
点击查看代码
 /**  * Start the Catalina daemon.  * @throws Exception Fatal start error  */ public void start() throws Exception {     if (catalinaDaemon == null) {         init();     }      Method method = catalinaDaemon.getClass().getMethod(start, (Class [])null);     method.invoke(catalinaDaemon, (Object [])null); }