Maven底层容器Plexus Container的前世今生,一代芳华终闭幕

前言

说实话,我十分地纠结,大家平时只是用Maven,对于外部的实现其实也不关怀,我当初非要拉着大家给大家讲。这就有个问题,Maven的外部,还是绝对没那么简略的,也算是个不小的工程了。

外围性能,大家是分明的,外部的执行流程,大家也大略猜的进去:

  1. 解析命令行参数
  2. 筹备各种上下文,简略的mvn clean就波及到以后我的项目的元数据pom.xml、settings.xml(次要是本地、近程仓库相干);
  3. 依据mvn clean或者mvn compile,找到对应的生命周期(大家应该都晓得maven的三个lifecycle吧);而后看看要执行生命周期中的哪些阶段,程序是啥(这个和打包形式也无关,jar/war时,打包组件就不同);
  4. 程序执行生命周期中的每个阶段的时候,去找到对应的绑定的插件,而后执行插件(执行插件又包含:依据插件坐标,去本地仓库/近程仓库找对应的artifact,以及解析artifact中的插件元数据,元数据中会通知你,反对传哪些参数,参数类型是啥)
  5. 执行实现后,返回后果。

这么一个不小的工程,想必,还是会有很多对象相互依赖的,在没有依赖注入前,都是靠new,或者是工厂来缓解;我查了下历史材料,maven的开发者在一篇文章中(https://blog.sonatype.com/201...),提到:

We knew we needed some sort of component framework, some standard mechanism to instantiate plugins and configure them based on a set of configuration points

大略意思,他们也发现他们须要一个组件框架,一种标准化可能实例化组件的机制,可能基于一组配置来配置这些组件。

阐明,晚期的Maven开发者们,曾经意识到了本人可能须要一个相似容器的货色,那,为啥没有选用Spring呢?

下边,让咱们来层层揭开历史的面纱。

Maven初起步

查阅了Maven官网,发现Maven的第一个版本,居然早在2002年。(http://jakarta.apache.org/sit...)。

2003年,成为Apache顶级我的项目,2004年,公布1.0版本。

另外一边,咱们熟知的,无人不知无人不晓的Spring呢,第一个版本是什么时候呢?

The first version was written by Rod Johnson), who released the framework with the publication of his book Expert One-on-One J2EE Design and Development in October 2002.

这里说,spring的第一个版本同样公布于2002年,是跟随着Rod Johnson的书《Expert One-on-One J2EE Design and Development 》一起公布的。也是在03年,应用Apache 2.0 License,公布了一个版本;04年3月,公布了一个生产用的版本。

所以,咱们就能够了解,Maven的开发者在那篇2010年的文章里写的:

When we started the Maven project, dependency injection was still developing. Spring was just starting out and the Avalon project at Apache was really the only IoC framework around

简略说,就是,当开始搞Maven的时候,依赖注入还在倒退当中。Spring刚起步,Avalon我的项目,也仅仅只是一个ioc框架。

既然内部不成熟,他们的重心也不在这些依赖注入框架下面,所以他们就基于本人的需要,本人搞了一个适宜Maven的,它就叫:Plexus。

Maven晚期:做本人的IOC容器

Plexus我的项目

Plexus: 发音(plekss),a network of nerves or vessels in the body.

Plexus,中文意思,可能是神经网络或者血管网络,就因为血管是网状的,像他么互联网一样,所以被拿来当一个框架名了吗,maybe。

这个我的项目(官网:https://codehaus-plexus.githu...),定位是做容器。官网不晓得为啥,这会打不开,然而我发现一个记录互联网历史的网站:https://web.archive.org/web/2...。

Plexus我的项目,基于其中的Plexus Container子项目,应用程序能够应用基于组件的编程形式,构建模块化的、可复用的组件。Plexus相似其余的IOC框架,如Spring,但它还额定提供了很多个性,如:组件生命周期治理、组件实例化策略、嵌套容器、组件配置、主动注入、组件依赖、各种依赖注入形式(如结构器注入、setter注入、字段注入)。

总的来说,我个人感觉,这些个性,Spring如同也有啊,哈哈。

Plexus 下组件

Plexus这么一个我的项目,当然不止容器,大略有如下几个:

  • Plexus Classworlds,类加载器框架,Maven至今还在用,个人感觉也挺不错,举荐学习学习;
  • Plexus Container,IOC容器,Maven 1.x/2.x在用,3.0版本后,Maven本身也没有再应用了
  • Plexus Components

    Maven的工作就是和各种文件、目录打交道,这期间,会积淀进去很多专用组件:

    1. IO相干的,Plexus IO Components,它的maven坐标:
    <!-- https://mvnrepository.com/artifact/org.codehaus.plexus/plexus-io --><dependency>    <groupId>org.codehaus.plexus</groupId>    <artifactId>plexus-io</artifactId>    <version>3.2.0</version></dependency>
    1. 归档相干的,Plexus Archiver Component,maven坐标:

      <!-- https://mvnrepository.com/artifact/org.codehaus.plexus/plexus-archiver --><dependency>    <groupId>org.codehaus.plexus</groupId>    <artifactId>plexus-archiver</artifactId>    <version>4.2.5</version></dependency>
    2. cli相干,Plexus CLI
    3. 编译相干,Plexus Compiler
    4. Digest/Hashcode相干,Plexus Digest / Hashcode Components
    5. 国际化相干,i18n

    还有些其余的,我懒得列举了,大家本人看吧,https://web.archive.org/web/2...

  • Plexus Maven Plugin,用来反对Maven插件
  • Plexus Utils,工具类,至今仍在用

Plexus组件的现状

关上我本机的maven装置目录的lib,发现plexus相干的,仅剩少数几个了,如,下图的几个工具:

还有下图的启动类:

当初说好的IOC容器,后果Maven怎么本人也不必了呢?咱们来看看这个容器相干的组件吧。

容器相干的,一共4个maven组件。

这外面,plexus-component-annotations咱们刚看到,还在用,他是干嘛的呢,就是相似于Spring外面的注解,比方@Service/@Controller这种。

而plexus-component-metadata,是一个maven插件,用来生成组件的xml,有点像咱们的spring的xml时代,这个工程呢,就能够剖析咱们代码,帮咱们生成spring的bean.xml这种,就不须要手动配置依赖了。

这外面,真正的IOC容器实现,就是:plexus-container-default。

该组件,能够说是Maven的结发妻子,陪伴了Maven的青年期间,咱们看看这个组件是什么时候第一次退场的。

下边是它1.0版本的坐标:

<!-- https://mvnrepository.com/artifact/plexus/plexus-container-default --><dependency>    <groupId>plexus</groupId>    <artifactId>plexus-container-default</artifactId>    <version>1.0-alpha-1</version></dependency>

工夫是2005年。

而maven什么时候开始应用该容器呢,我没有查到maven 1.x版本的pom依赖,然而在2.0.alpha版本,曾经看到了该容器的身影:

此时,是2006年。

仅仅几年后,在maven 3.0的版本中,曾经不再有plexus ioc容器的身影,却来了一个不请自来。

在开始说不请自来之前,咱们还是要问问,plexus ioc容器,为啥就不行了呢?对这个历史感兴趣的,能够间接看:

https://blog.sonatype.com/201...

为什么呢?因为时代变了,此时,Spring曾经开始成为事实上的IOC容器规范,不过,尽管Spring在利用开发畛域,所向无敌,然而在各种框架中,框架开发者们还是感觉Spring太重了,一下就要引入好几个jar包,切实是过于臃肿。因而,google 在2007年的时候,就推出了一个轻量级的依赖注入框架,叫google guice。

此时,通过多年的迭代,在2010年前后,guice曾经比拟成熟了,在google外部也而失去了广泛应用,且依赖注入这个畛域,也在继续一直地倒退中,比方java官网定义了相干的规范api。

而此时,Maven的开发者们曾经难以同时保护Plexus IOC容器(比方适配java官网新出规范,和周边Spring兼容等等各类工作),因而,Maven决定,为了节俭精力,Maven将不再基于Plexus IOC容器,而是应用Guice,当前就只管用了,而guice的保护降级,天然有Guice的开源团队去跟进。

说了那么多,为了留念Plexus Container的闭幕,咱们还是来看看,这个IOC组件到底怎么用的吧?

Plexus IOC容器初应用

例子也是来自于官网,我依据文档,整顿成了一个maven module。大家能够拉代码下来。

https://gitee.com/ckl111/mave...

1.像所有的IOC容器一样,定义一个接口和实现类

public interface Cheese{    /** The Plexus role identifier. */    String ROLE = Cheese.class.getName();    /**     * Slices the cheese for apportioning onto crackers.     * @param slices the number of slices     */    void slice( int slices );    /**     * Get the description of the aroma of the cheese.     * @return the aroma     */    String getAroma();}
public class ParmesanCheese        implements Cheese{    public void slice( int slices )    {        throw new UnsupportedOperationException( "No can do" );    }    public String getAroma()    {        return "strong";    }}

就像spring的xml时代一样,定义组件的依赖关系

留神一下,这里的组件配置中,有三个元素:

  • role,此处放:接口名称
  • role-hint,此处放:实现类的qualifier,相似spring中,一个接口多个实现类,咱们就会给这多个实现类,定义一个显示的名字,@Qualifier
  • implementation,实现类的类名。

ok,这就定义好了一个组件。

咱们开始测试。

从容器中获取组件

public class App {    public static void main(String args[]) throws Exception    {        // 1  定义一个容器,容器会去加载classpath下的META-INF/Plexus/component.xml中的组件        PlexusContainer container= new DefaultPlexusContainer();        // 2 获取组件,实现依赖注入等工作        Cheese cheese = (Cheese) container.lookup( Cheese.ROLE, "parmesan" );        // 3 应用组件        System.out.println( "Parmesan is " + cheese.getAroma() );        // 4 销毁容器        container.dispose();    }}

其余用法

如果这个组件,依赖其余组件,怎么办呢,怎么注入呢?

我在maven源码工程里看到这样的组件配置,想必,就是像如下这样配置。

<?xml version="1.0"?><component-set>  <components>    <component>      <role>org.apache.maven.profiles.activation.ProfileActivator</role>      <role-hint>faulty</role-hint>      <implementation>org.ext.App</implementation>      <requirements>        <requirement>          <role>org.apache.maven.artifact.ArtifactResolver</role>          <field-name>artifactResolver</field-name>        </requirement>      </requirements>    </component>  </components></component-set>

循环依赖怎么办呢?释怀,人家也是能够解决的,这里就不截图了。

总结

一个组件,写进去,居然感觉就像是也有感情一样,也是有点意思。不过不管怎么说,Plexus Container在陪伴Maven度过了整个2.x版本后,终将落下帷幕。

接下来,是Guice的时代,而当初,十多年后的2021年,Guice仍然稳固地撑持着Maven。Guice足够优良,在此之前,我居然简直没什么理解,Guice在哪些地方有利用呢,简略列举几个:

  • google外部
  • scalatest
  • TestNG
  • Caffeine Cache
  • Spring Security Config
  • elastic search
  • jenkins

以及一些其余的我不太熟悉的技术,大家能够查看:

https://mvnrepository.com/art...

本文由博客一文多发平台 OpenWrite 公布!