关于java:曹工杂谈Maven底层容器Plexus-Container的前世今生一代芳华终落幕

6次阅读

共计 6167 个字符,预计需要花费 16 分钟才能阅读完成。

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: 发音 (ˈpleksəs),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 公布!

正文完
 0