Tomcat虽然作为轻量级的Web Server,但是其设计精巧,作为一个Server,方方面面的知识都有涉及。今天我们就来研究一下他的启动类Bootstrap。
一、Class Bootstrap
Bootstrap类作为程序的入口自然是main(),而跟Bootstrap启动类相关的有:
ClassLoaderFactory : 负责创建类加载器。
SecurityClassLoad : 负责加载已经编译好的整个Server的class文件。
CatalinaProperties: 作为属性加载器,读取整个Server的系统属性,也读取同包中的Catalina.Properties的属性。
可以看出,Bootstrap类启动的方式可以说就是创建类加载器,加载Server 的class文件。
-----------------------------------------------------------------------
二、具体实现
首先是-----------Variables----------
1 public final class Bootstrap { 2 3 private static final Log log = LogFactory.getLog(Bootstrap.class); 4 private static Bootstrap daemon = null; //文件路径 5 private static final File catalinaBaseFile; 6 private static final File catalinaHomeFile; 7 private static final Pattern PATH_PATTERN = Pattern.compile("(\".*?\")|(([^,])*)"); 8 private Object catalinaDaemon = null; //类加载器 9 ClassLoader commonLoader = null;10 ClassLoader catalinaLoader = null;11 ClassLoader sharedLoader = null;
静态语句块static{...}对常量catalinaBaseFile,catalinaHomeFile进行了赋值操作。
1 static { 2 String userDir = System.getProperty("user.dir"); userDir="D:\IdeaProject\tomcatmini" 3 String home = System.getProperty("catalina.home"); home=null 4 File homeFile = null; 5 File f; 6 if (home != null) { 7 f = new File(home); 8 9 try {10 homeFile = f.getCanonicalFile();11 } catch (IOException var9) {12 homeFile = f.getAbsoluteFile();13 }14 }15 16 File baseFile;17 if (homeFile == null) { homeFile = null18 f = new File(userDir, "bootstrap.jar");19 if (f.exists()) {20 baseFile = new File(userDir, "..");21 22 try {23 homeFile = baseFile.getCanonicalFile();24 } catch (IOException var8) {25 homeFile = baseFile.getAbsoluteFile();26 }27 }28 }29 30 if (homeFile == null) { homeFile = null进入此分支,31 f = new File(userDir);32 33 try {34 homeFile = f.getCanonicalFile();35 } catch (IOException var7) {36 homeFile = f.getAbsoluteFile(); homeFile = "D:\IdeaProject\tomcatmini"37 }38 }39 40 catalinaHomeFile = homeFile;41 System.setProperty("catalina.home", catalinaHomeFile.getPath());42 String base = System.getProperty("catalina.base"); base = null43 if (base == null) {44 catalinaBaseFile = catalinaHomeFile; catalinaBaseFile = "D:\IdeaProject\tomcatmini" 45 } else {46 baseFile = new File(base);47 48 try {49 baseFile = baseFile.getCanonicalFile();50 } catch (IOException var6) {51 baseFile = baseFile.getAbsoluteFile();52 }53 54 catalinaBaseFile = baseFile;55 }56 57 System.setProperty("catalina.base", catalinaBaseFile.getPath());58 }
然后是-----------main()-----------
1 public static void main(String[] args) { 2 if (daemon == null) { daemon == null 3 Bootstrap bootstrap = new Bootstrap(); 4 5 try { 6 bootstrap.; 点此可以超链接哦 7 } catch (Throwable var3) { 8 handleThrowable(var3); 9 var3.printStackTrace();10 return;11 }12 13 daemon = bootstrap;14 } else {15 Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);16 }17 18 try {19 String command = "start";20 if (args.length > 0) {21 command = args[args.length - 1];22 }23 24 if (command.equals("startd")) {25 args[args.length - 1] = "start";26 daemon.load(args);27 daemon.start();28 } else if (command.equals("stopd")) {29 args[args.length - 1] = "stop";30 daemon.stop();31 } else if (command.equals("start")) {32 daemon.setAwait(true);33 daemon.load(args);34 daemon.start();35 } else if (command.equals("stop")) {36 daemon.stopServer(args);37 } else if (command.equals("configtest")) {38 daemon.load(args);39 if (null == daemon.getServer()) {40 System.exit(1);41 }42 43 System.exit(0);44 } else {45 log.warn("Bootstrap: command \"" + command + "\" does not exist.");46 }47 } catch (Throwable var4) {48 Throwable t = var4;49 if (var4 instanceof InvocationTargetException && var4.getCause() != null) {50 t = var4.getCause();51 }52 53 handleThrowable(t);54 t.printStackTrace();55 System.exit(1);56 }57 58 }
----------------------init()----------------------
public void init() throws Exception { 此方法内部创建类加载器和安全加载相关类文件还有设置setContextClassLoader this.; 初始化类加载器 Thread.currentThread().setContextClassLoader(this.catalinaLoader); 设置当前线程为ContextClassLoader SecurityClassLoad.securityClassLoad(this.catalinaLoader); catalinaLoader作为类加载器加载去加载catalina服务器core,session,util等文件。 if (log.isDebugEnabled()) { log.debug("Loading startup class"); } Class startupClass = this.catalinaLoader.loadClass("startup.Catalina"); Object startupInstance = startupClass.newInstance(); if (log.isDebugEnabled()) { log.debug("Setting startup class properties"); } String methodName = "setParentClassLoader"; Class [] paramTypes = new Class[]{Class.forName("java.lang.ClassLoader")}; Object[] paramValues = new Object[]{this.sharedLoader}; Method method = startupInstance.getClass().getMethod(methodName, paramTypes); method.invoke(startupInstance, paramValues); this.catalinaDaemon = startupInstance; }
-----------initClassLoaders-------------
private void initClassLoaders() { try{ this.commonLoader = this.createClassLoader("common", (ClassLoader)null); if (this.commonLoader == null) { this.commonLoader = this.getClass().getClassLoader(); } this.catalinaLoader = this.createClassLoader("server", this.commonLoader); this.sharedLoader = this.createClassLoader("shared", this.commonLoader); } catch (Throwable var2) { handleThrowable(var2); log.error("Class loader creation threw exception", var2); System.exit(1); } }
-------
private ClassLoader createClassLoader(String name, ClassLoader parent) throws Exception { String value = CatalinaProperties.getProperty(name + ".loader"); System.out.println(value); if (value != null && !value.equals("")) { value = this.replace(value); Listrepositories = new ArrayList(); String[] repositoryPaths = getPaths(value); String[] arr$ = repositoryPaths; int len$ = repositoryPaths.length; for(int i$ = 0; i$ < len$; ++i$) { String repository = arr$[i$]; try { new URL(repository); repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.URL)); } catch (MalformedURLException var11) { if (repository.endsWith("*.jar")) { repository = repository.substring(0, repository.length() - "*.jar".length()); repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.GLOB)); } else if (repository.endsWith(".jar")) { repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.JAR)); } else { repositories.add(new ClassLoaderFactory.Repository(repository, ClassLoaderFactory.RepositoryType.DIR)); } } } return ClassLoaderFactory.createClassLoader(repositories, parent); } else { return parent; } }
-----------------------