我想知道 Gradle 是如何实现这种机制的:将特定方法添加到脚本 block 中,该方法仅在该 block 中有效。
例如,如果我想使用implementation
方法,我必须apply plugin: 'java'
,但我只能使用implementation
在 dependencies{}
最佳答案
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 插件后,您的配置
将拥有api
、implementation
和so 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/