环境:tomcat7.0.28
坚持一下,把源码看完,勤奋一点,不要在懒惰了,你已经落下别人很多了
一、总体流程
二、代码解析
在Bootstrap的init方法中,主要工作分5步,首先是初始化变量的问题,也就是设置设置系统变量的操作,调用System.setProperty方法。然后是初始化类加载器,设置catalinaLoader绑定为当前线程,最后用catalinaLoader加载类Catalina ,并且给类Catalina的parentClassLoader赋值为catalinaLoader。
初始化完毕,调用Catalina的start方法。
1、 Bootstrap.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);
}
通过代码可以看到,总共创建了3个classLoader,commonLoader、catalinaLoader、sharedLoader,
最终调用的方法是createClassLoader(String name, ClassLoader parent)
2、 Bootstrap.createClassLoader()方法解析
String value = CatalinaProperties.getProperty(name + ".loader");
if ((value == null) || (value.equals("")))
return parent;
value = replace(value);
List<Repository> repositories = new ArrayList<Repository>();
StringTokenizer tokenizer = new StringTokenizer(value, ",");
while (tokenizer.hasMoreElements()) {
String repository = tokenizer.nextToken().trim();
if (repository.length() == 0) {
continue;
}
// Check for a JAR URL repository
try {
@SuppressWarnings("unused")
URL url = new URL(repository);//此处抛异常,如果字符串指定未知协议
repositories.add(
new Repository(repository, RepositoryType.URL));
continue;
} catch (MalformedURLException e) {
// Ignore
}
// Local repository
if (repository.endsWith("*.jar")) {
repository = repository.substring
(0, repository.length() - "*.jar".length());
repositories.add(
new Repository(repository, RepositoryType.GLOB));
} else if (repository.endsWith(".jar")) {
repositories.add(
new Repository(repository, RepositoryType.JAR));
} else {
repositories.add(
new Repository(repository, RepositoryType.DIR));
}
}
return ClassLoaderFactory.createClassLoader(repositories, parent);
这一部分代码总共就做了2份工作,
(1)根据传入方法的name属性去 catalina.properties配置文件中找到对应的 name.loader指定的值,封装成资源库。catalian.properties的内容如下:
(2)调用工厂方法创建类加载器 ClassLoaderFactory.createClassLoader(repositores,parent)
该方法主要返回了一个URLClassLoader,如果parent为空,则URLClassLoader的父类加载器为SystemClassLoader,也可以理解为是AppClassLoader,感兴趣的同学可以去了解一下JAVA 类加载器的双亲委派模型。如果parent不为空,则指定URLClassLoader的父类加载器。
结论1:Bootstrap的三个类加载器都是URLClassLoader的类加载器的对象,并且,如果catalina.properties中的server.loader和shared.loader没有数据的话,则三者指向的是同一个类加载器的实例,结合tomcat7的文档结构来看,可以确定commonLoader=catalinaLoader=sharedLoader。
对Catalina.load方法解析放在第二节。
对Catalina.start方法解析放在第三节。