一句话概况: 不考虑缓存, 那么装载路径就是,先Classpath, 然后War包,当前工程, 最后才是Tomcat相关目录. 不考虑缓存,是因为缓存只是用来加快速度,对外不调用展现出的逻辑效果是可以忽略的.
下图是一个概况的流程图, 简介起见,绘图过程中移除了缓存功能. (个了感觉还是有些逻辑还是有些复杂的,图画出来了,自己看着都觉得还是不清楚,但是也没发现可以改进的地方)
下面是关键的代码,已经添加了注释.
//WebappClassLoader.loadClass (Tomcat 7.0) @Override public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { if (log.isDebugEnabled()) log.debug("loadClass(" + name + ", " + resolve + ")"); Class<?> clazz = null; //检查当前ClassLoad是否已经停止了 // Log access to stopped classloader if (!started) { try { throw new IllegalStateException(); } catch (IllegalStateException e) { log.info(sm.getString("webappClassLoader.stopped", name), e); } } //检查缓存1,Class是否已经被当前Class"实例"装载过 // (0) Check our previously loaded local class cache clazz = findLoadedClass0(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } //ClassLoader检查缓存2,Class是否已经被父类"实例"装载过 // (0.1) Check our previously loaded class cache clazz = findLoadedClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Returning class from cache"); if (resolve) resolveClass(clazz); return (clazz); } //ClassLoader装载系统classpath下面的类, 阻止webapp覆盖了J2SE的类 // (0.2) Try loading the class with the system class loader, to prevent // the webapp from overriding J2SE classes try { clazz = system.loadClass(name); if (clazz != null) { if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } //安全检查 // (0.5) Permission to access this class when using a SecurityManager if (securityManager != null) { int i = name.lastIndexOf('.'); if (i >= 0) { try { securityManager.checkPackageAccess(name.substring(0,i)); } catch (SecurityException se) { String error = "Security Violation, attempt to use " + "Restricted Class: " + name; log.info(error, se); throw new ClassNotFoundException(error, se); } } } //默认的返回值为false, //delegate = false //filter(name) 通过一个List指定哪些package里面的Class使用双亲委派模式,但是默认这个List是空 //比如包名以Java开头的,就需要使用双亲委派模式,不过这一点"部分"由 (0.2) 在上面已经实现了 boolean delegateLoad = delegate || filter(name); //针对一些明确指定的package,使用双亲委派模式加载 // (1) Delegate to our parent if requested if (delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader1 " + parent); ClassLoader loader = parent; if (loader == null) loader = system; try { clazz = Class.forName(name, false, loader); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore //如果(1)通过双亲委派加载发生异常, 忽略异常, } } //尝试从本地加载Class( 如果(1)通过双亲委派加载发生异常, 忽略异常,也会走到这一步) // (2) Search local repositories if (log.isDebugEnabled()) log.debug(" Searching local repositories"); try { clazz = findClass(name); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from local repository"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } //最后依旧没有成功, 忽略所有配置,再次尝试一下双亲加载模式加载 // (3) Delegate to parent unconditionally if (!delegateLoad) { if (log.isDebugEnabled()) log.debug(" Delegating to parent classloader at end: " + parent); ClassLoader loader = parent; if (loader == null) loader = system; try { clazz = Class.forName(name, false, loader); if (clazz != null) { if (log.isDebugEnabled()) log.debug(" Loading class from parent"); if (resolve) resolveClass(clazz); return (clazz); } } catch (ClassNotFoundException e) { // Ignore } } //最后如果依旧没有成功,则抛出异常 throw new ClassNotFoundException(name); }
相关推荐
《细说PHP》配套源码,很罕见的案例哟 /*==================================================================*/ /* 文件名:comm_pro.php */ /* 概要: 文章评论的处理页面. ...
《细说PHP》是一本深入浅出的PHP编程教材,旨在帮助读者全面理解PHP语言的原理和实际应用。配套源码提供了书中各个章节实例的完整代码,让学习者能够亲手实践,加深对PHP编程的理解。以下是对这些源码中涉及的知识点...
《细说PHP》是一本深度解析PHP编程语言的书籍,其光盘源码包含了书中所有实例和示例的完整代码,对于学习和深入理解PHP有着极高的价值。这份源码的特点在于注释详尽,可以帮助读者更好地理解每段代码的功能和实现...
《细说PHP》是一本广泛受到PHP初学者和进阶者欢迎的教程书籍,其光盘源码包含了大量的实例和练习,旨在帮助读者深入理解PHP编程语言的各种概念和技术。源码通常包括书中提及的示例程序、脚本以及可能的项目文件,...
细说PHP第二版 源码 <html> <!-- HTML文件开始 --> <head> <!-- HTML文件的头部开始 --> ... ... <!-- HTML文件的头部内容 --> </head> <!-- HTML文件的头部结束 --> <body> <!-- ...
最后,源码分析还有助于理解PHP的最佳实践和设计模式。比如,如何编写可读性强、可维护性高的代码,如何组织项目结构,以及如何使用命名空间和自动加载来简化代码管理。通过实践,你可以培养出良好的编程习惯,提升...
而对有经验的开发者来说,这些源码则提供了复习和查找特定功能实现的好去处。 总的来说,《细说PHP》配套源码.zip是一个珍贵的学习资源,无论你是PHP新手还是有一定经验的开发者,都可以从中受益匪浅。通过逐行阅读...
5. 错误处理和调试:源码中可能会有错误报告、异常处理和日志记录的实例,这些是提高程序健壮性的重要手段。 6. 函数库应用:PHP拥有丰富的内置函数库,如字符串处理、数组操作、文件系统操作等。通过源码,读者...
《细说Android 4.0 NDK编程》一书深入探讨了Android系统中NDK(Native Development Kit)的使用和编程技巧,旨在帮助开发者利用C和C++等原生语言来开发高性能、低级别的Android应用。NDK是Google提供的一组工具集,...
《细说PHP》是一本深度解析PHP编程语言的专业书籍,其光盘源码rar压缩包包含了大量的示例代码和练习项目,旨在帮助读者深入理解PHP的语法、函数库以及实际应用开发技巧。这本书覆盖了从PHP的基础知识到高级特性的全...
《细说PHP》是高洛峰撰写的一本深入解析PHP编程的书籍,其配套源码提供了丰富的实例和代码示例,旨在帮助读者更好地理解和实践PHP编程。这本书涵盖了PHP的各个方面,从基础语法到高级特性,从函数应用到面向对象编程...
细说php 4th 在线教育系统EDUPlayer源码28章 项目源码
《细说PHP》是一本广泛受到PHP初学者和开发者欢迎的教材,它的配套源码是学习和实践PHP编程的重要资源。这本书深入浅出地讲解了PHP语言的基础知识、Web开发技术以及高级应用,旨在帮助读者从零基础快速掌握PHP编程,...
《细说PHP源码》是针对PHP编程语言深入解析的一部教程,由PHP兄弟连倾情打造,旨在帮助开发者更全面、深入地理解PHP的内部工作机制,提升技术水平,努力成为PHP开发的大牛。通过学习本教程,我们可以了解到PHP源码...
8. **错误处理与日志记录**:良好的错误处理机制是任何项目必备的,BroCMS可能会有错误捕获和日志记录功能,方便调试和问题排查。 9. **模板布局**:BroCMS的前端部分可能使用了HTML、CSS和JavaScript,展示动态...
"细说php中的cms项目源码"是一个专为初学者设计的教程,旨在帮助他们理解和学习如何使用PHP开发CMS系统。这个教程基于"细说php"的第二版,最后一章的内容,提供了实际的代码示例,方便开发者进行实践。 首先,我们...