maven源码阅读之二(plexus-classworlds)

maven源码阅读之二(plexus-classworlds)plexus 本来是想构建一个 IOC 容器 但是现在这个 IOC 容器被 eclipse sisu 代替了 eclipse sisu 是集成了 google 的 guice 和的 IOC 容器 这个在后面的文章中具体分享 而 plexus 为 maven 提供了很多的组件 其中 plexus classworlds 就是很重要的一个

大家好,我是讯享网,很高兴认识大家。

 plexus本来是想构建一个IOC容器,但是现在这个IOC容器被eclipse-sisu代替了,eclipse-sisu是集成了google的guice和的IOC容器,这个在后面的文章中具体分享,而plexus为maven提供了很多的组件,其中plexus-classworlds就是很重要的一个,plexus-classworlds主要是对java的ClassLoader进行了扩展,提供了一个可以从其他的classLoader中导入class的有向图的依赖结构,并且提供了一个classLoader的加载器池ClassWorld。

总体介绍

可以看到plexus-classworlds的代码很少,主要是ClassRealm,Strategy,ClassWorld,ClassWorldListener以及Launcher。

  • ClassRealm:主要是继承了UrlClassLoader,存储了从其parentClassLoader,或者其它的ClassRealm加载的packet,并重写了loadClass,将loadClass操作给Strategy进行操作
  • Strategy:主要是从外部导入类,从parentLoader导入类,还是从自身加载类的顺序来确定不同的策略。
  • ClassWorld: ClassWorld是ClassRealm的池,主要是存储一个id->classRealm的map,以及一系列ClassWorldListener提供外部在classRealm在创建和销毁时的扩展
  • ClassWorldListener: 主要定义了在ClassRealm在ClassWorld中创建和销毁时的回调方法。
  • Launcher: 这个主要时通过配置文件来创建ClassWorld,以及启动的main类,maven就是通过这个类来进行启动的。


讯享网

ClassRealm

classRealm继承了URLClassLoader类,其自身的classLoader导入jar包还是和URLClassLoader一样,通过addURl方法将jar包注册到父类ClassLoader中。classRealm主要是维护了两个集合,foreignImports和parentImports分别存储了这个classRealm从别的classLoader中导入的packet和从parent导入的packet,需要注意的是此处的parentClassLoader不是双亲委派系统的parentClassLoader,是外部注册的一个classLoader。

public class ClassRealm extends URLClassLoader{ private ClassWorld world; private String id; //从别的classLoader中导入的packetName->ClassLoader的键值对 private SortedSet<Entry> foreignImports; //从父类导入的packetName->ClassLoader的键值对 private SortedSet<Entry> parentImports; //加载策略 private Strategy strategy; //父classLoader,这个父classLoader不是双亲委派模型的类加载器,是外部注入的这个classLoader的父classLoader private ClassLoader parentClassLoader; ... }

讯享网

loadClass和findClass

ClassRealm重写了URLClassLoader的loadClassfindClass,其中loadClass最终调用的就是unsynchronizedLoadClasss,再loadCass方法中则先调用父类的loadClass,通过父类的loadClass方法先从已经加载了的类中,双亲委派的父classLoader中尝试加载类,其最终会调用findClass在本类中找对应的class,但是重写的findClass直接抛出ClassNotFoundException导致调用父类的loadClass是无法在本类中找到。在父类的loadClass没有找到对应的类时,则会通过stategy来加载对应类,strategy中最终调用的是loadClassFromImport,loadClassFromSelf,loadClassFromParent这三个方法来加载对应的类的。

loadClassFromImport,loadClassFromSelf和loadClassFromParent

这三个方法是classRealm本地找class的方式,一种是从外部注入的其他的classLoader中找,一种是从本地addURL方法加入的jar中查找,再有一种则是从其parentClassLoader中进行查找,而上面的不同的strategy则是这三个方法的调用顺序的不同。

根据maven的启动脚本分析

看maven的启动的脚本,可以看到它是调用boot目录下的plexus-classworlds中的Launcher类来进行相关的处理的,而其配置文件则是/bin目录下的m2.conf文件

下面来看一下m2.conf这个配置文件,可以看到这个配置文件配置了主类是id为plexus.core的ClassRealm的MavenCli类,对于plexus.core这个ClassRealm的配置则是加载了${maven.conf}/logging文件夹下的关于日志的配置文件,将lib/ext目录的jar文件都加载进来(这个是可选的加入,即有没有都可以),将lib/文件夹下面的jar文件都加入到对应的ClassRealm中。并且其还将环境变量maven.conf=${maven.home}/conf。

 

小讯
上一篇 2025-02-07 11:53
下一篇 2025-04-02 09:33

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/66647.html