Gradle 生态系统源码分析

Gradle 进阶 第八篇

宁为玉碎,不为瓦全

Gradle Project 下卷

上一章讲到 Gradle 的 ConfigurationContainer,ConfigurationContainer 里面包含了一些系列的 Configuration,而 Configuration 又继承了 FileCollection 接口。其实现类 DefaultConfiguration 中包括了对外发布的一个集合,以及构建依赖的一个集合。以供 project 管理依赖,并且对外提供构建好的 Artifact。

public class DefaultConfiguration extends AbstractFileCollection implements ConfigurationInternal, MutationValidator {
    ...
    private DefaultDependencySet allDependencies;
    ...
    private DefaultPublishArtifactSet allArtifacts;
}

ArtifactHandler

ArtifactHandler 这个类用于定义要发布的 artifact,并将它们添加到配置中。创建发布工件并不意味着要创建存档。创建的是表示要发布的文件的域对象以及如何发布的信息(这是源码里注解的翻译),这个类创建于 2009 年,gradle 后面又加入了 Ivy 以及 Maven (2013)作真正的发布逻辑,所以从源码上 ArtifactHandler 更多的是暴露了在脚本中往 configuration 里添加 artifact 的能力。
这里举一个栗子:

 configurations {
    //declaring new configuration that will be used to associate with artifacts
   schema
 }
 
 task schemaJar(type: Jar) {
    //some imaginary task that creates a jar artifact with some schema
 }
 
 //associating the task that produces the artifact with the configuration
  artifacts {
    //configuration name and the task:
    schema schemaJar
 }

栗子里面首先创建一个名叫 schema 的 configuration,接着创建了一个 task,task 主要是用来生成 artifact,最后调用 DefaultProject 的 artifacts 方法传入一个闭包作为参数。

其实 ArtifactHandler 接口只有三个方法,每个方法都有一个 String 类型的 configurationName 参数指定 configuration,还有一个 Object 类型的 artifactNotation,这里对 artifactNotation 有一定的限制:

  • PublishArtifact
  • AbstractArchiveTask
  • RegularFile or Directiory
  • File
  • Map
public interface ArtifactHandler {
   
    PublishArtifact add(String configurationName, Object artifactNotation);

    
    PublishArtifact add(String configurationName, Object artifactNotation, Closure configureClosure);

    PublishArtifact add(String configurationName, Object artifactNotation, Action configureAction);
}

这里需要注意一点,在 gradle 源码中有两个 artifact 接口, PublishArtifact 和 PublicationArtifact,这里所讨论的是 PublishArtifact,而 PublicationArtifact 以及其子接口 MavenArtifact 和 IvyArtifact 会在后面讲发布到仓库的时候讲解。

这里就会有一个疑问,加入 configuration 的这些 artifacts 到底在什么时候去使用。这里以 BasePlugin 举一个栗子:

 public class BasePlugin implements Plugin {
    public static final String ASSEMBLE_TASK_NAME = LifecycleBasePlugin.ASSEMBLE_TASK_NAME;/// "assemble"


    private void configureAssemble(final ProjectInternal project) {
        project.getTasks().named(ASSEMBLE_TASK_NAME, task -> {
            task.dependsOn(task.getProject().getConfigurations().getByName(Dependency.ARCHIVES_CONFIGURATION).getAllArtifacts().getBuildDependencies());
        });
    }
 }

这里我们看到在 apply 了 BasePlugin 之后,会调用到 configureAssemble 这个函数,在里面,创建了 assemble 的 Task,并且将这个 task 依赖了当前 Project 的 archives configuration 的所有 artifacts 的依赖。这句话有点绕,需要对着源码体会。

ExtensibleDynamicObject

ExtensibleDynamicObject 我在第二章讲过了,在动态调用系统中详细描述了,这个类的作用,有不清楚的可以回看一下,这里就不在赘述。

你可能感兴趣的:(Gradle 生态系统源码分析)