java - Gradle Plugin 如何将方法添加到特定 block ?

标签 java gradle groovy

我想知道 Gradle 是如何实现这种机制的:将特定方法添加到脚本 block 中,该方法仅在该 block 中有效。

例如,如果我想使用implementation方法,我必须apply plugin: 'java',但我只能使用implementationdependencies{}

最佳答案

dependencies block 只是一个 DependencyHandler . 默认实现是 DefaultDependencyHandler . 请注意,它实现了 MethodMixIn :

A decorated domain object type may optionally implement this interface to dynamically expose methods in addition to those declared statically on the type. Note that when a type implements this interface, dynamic Groovy dispatch will not be used to discover opaque methods. That is, methods such as methodMissing() will be ignored.

所以,这个 mixin 类似于 methodMissing在 Groovy 中。 每当在 Groovy 对象上调用未知方法时,如果它有 methodMissing 方法,就会调用它。 MethodMixIn 的工作方式似乎类似。 它定义了一个方法:

MethodAccess getAdditionalMethods();

我们看看DefaultDependencyHandler中是如何实现的?

public MethodAccess getAdditionalMethods() {
    return dynamicMethods;
}

dynamicMethods 初始化为:

dynamicMethods = new DynamicAddDependencyMethods(configurationContainer, new DirectDependencyAdder());

让我们检查一下 DynamicAddDependencyMethods . 首先,它定义了一个 hasMethod,当存在具有给定名称的配置时返回 true:

public boolean hasMethod(String name, Object... arguments) {
    return arguments.length != 0 && configurationContainer.findByName(name) != null;
}

应用 Java 插件后,您的配置 将拥有apiimplementationso on 等对象。 . 所以,hasMethod("api") 将返回 true,而 hasMethod("API")false,除非您有另一个插件提供具有该名称的配置。

最后,每当配置名称像 dependencies block 中的函数一样使用时,就会调用 tryInvokeMethod:

public DynamicInvokeResult tryInvokeMethod(String name, Object... arguments) {
    if (arguments.length == 0) {
        return DynamicInvokeResult.notFound();
    }
    Configuration configuration = configurationContainer.findByName(name);
    if (configuration == null) {
        return DynamicInvokeResult.notFound();
    }

    List<?> normalizedArgs = CollectionUtils.flattenCollections(arguments);
    if (normalizedArgs.size() == 2 && normalizedArgs.get(1) instanceof Closure) {
        return DynamicInvokeResult.found(dependencyAdder.add(configuration, normalizedArgs.get(0), (Closure) normalizedArgs.get(1)));
    } else if (normalizedArgs.size() == 1) {
        return DynamicInvokeResult.found(dependencyAdder.add(configuration, normalizedArgs.get(0), null));
    } else {
        for (Object arg : normalizedArgs) {
            dependencyAdder.add(configuration, arg, null);
        }
        return DynamicInvokeResult.found();
    }
}

如您所见,它只是查找命名配置并向其添加依赖项。

这就是它的制作方式。

关于java - Gradle Plugin 如何将方法添加到特定 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62318216/

相关文章:

java - 有没有办法禁用 MotionLayout 可见性更改动画?

从 Android 远程控制的 JavaFX 程序

java - Android tesseract 数据路径

grails - 在Groovy中访问注释时出现IncompleteAnnotationException

java - 如何将项目(即从 github)导入到我的应用程序

android - 无法通过 Ubuntu 终端构建 Android Studio 项目

gradle - 在Gradle Tooling API的Groovy中将varargs作为第二个参数传递

performance - Grails 1.0 到 1.3 - 速度增加?

java - JMeter - 如何使用响应断言作为我的 If Controller 的条件

java - 有 Gradle 快速入门原型(prototype)吗?