我正在为内部公司使用创建自定义Gradle插件。它将为项目添加一些任务,并且插件用户可以自定义一个任务的行为。想法是拥有包含外部类名的插件属性。此类必须实现适当的接口才能正确使用。插件的任务将实例化该类的对象并在执行期间使用它。
原因 - 公司中不同的团队使用了几种相当不同的模式。所以这些"外部类"将被创建和发布。每个团队都可以选择用于构建配置的团队。如果有原因,甚至可以创建一个新的。所以我希望这个东西可以在构建级别上进行配置。
我未能在build.gradle脚本中设置此类依赖项。让我向您展示我尝试重现和解决问题的代码:
buildscript{
repositories {
mavenCentral()
maven{
url "http://our-internal-nexus/repository/maven-releases/"
}
dependencies{
classpath 'my.company:myplugin:0.1'
classpath 'my.other.company:extClass:0.1'
}
}
}
apply plugin: 'my.company.myplugin'
MyInput{
managerClass = "ExtClass"
}
myplugin - 我的插件的工件,以及extclass - 应该由插件的任务实例化的外部类。
当我尝试执行插件任务时: gradle hellotask 我收到错误:java.lang.ClassNotFoundException:ExtClass
我将一个代码放到hellotask类定义中以向我显示类路径。唯一显示的是C:/work/Projects/development/gradle-4.0.1/lib/gradle-launcher-4.0.1.jar
。所以对我来说,看起来没有路径可以通过gradle在运行时插件提供的extClass jar,因此无法找到它。
下面你可以找到plugin和extClass的源代码,如果这可能会有所帮助。
为myplugin
MyPlugin.java
package my.company;
import org.gradle.api.*;
//Plugin definition
public class MyPlugin implements Plugin<Project>{
@Override
public void apply(Project project){
project.getExtensions().create("MyInput", MyPluginExtension.class);
HelloTask helloTask = project.getTasks().create("helloTask", HelloTask.class);
}
}
HelloTask.java
package my.company;
import java.net.URL;
import java.net.URLClassLoader;
import org.gradle.api.*;
import org.gradle.api.tasks.*;
//Plugin task
public class HelloTask extends DefaultTask {
@TaskAction
public void action() {
//Print classpath
ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)sysClassLoader).getURLs();
for(int i=0; i< urls.length; i++) {
System.out.println(urls[i].getFile());
}
//Try to instantiate class
try {
MyPluginExtension extension = getProject().getExtensions().findByType(MyPluginExtension.class);
Object instance = Class.forName(extension.getManagerClass()).newInstance();
}
catch (ClassNotFoundException e) {
e.printStackTrace();
throw new GradleException("Class not found");
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new GradleException("IllegalAccessException");
} catch (InstantiationException e) {
e.printStackTrace();
throw new GradleException("InstantiationException");
}
}
}
MyPluginExtension.java
package my.company;
public class MyPluginExtension {
private String managerClass = null;
public String getManagerClass(){return this.managerClass;}
public void setManagerClass(String managerClass){ this.managerClass = managerClass;}
}
extClass
extClass.java
package my.other.company;
public class ExtClass {
public void ExtClass(){
System.out.println("Show me how it works!");
}
}
答案 0 :(得分:2)
即使你已经回答了自己的问题(你也可以接受),我想补充一点:
如果您想提供在插件例外中设置类的选项,为什么不让用户通过指定Class<?>
而不是String
来直接设置类? classpath
文件中提供了build.gradle
个依赖关系中添加的每个类。您还需要指定包,但您也可以像Java一样import
。此外,Groovy不希望您使用.class
后缀,您只需将类设置为扩展属性:
import my.other.company.ExtClass
[...]
MyInput {
managerClass = ExtClass
}
答案 1 :(得分:0)
好的,因为一旦你发布问题就会立即回答。 需要更改managerClass =&#34; ExtClass&#34; to managerClass =&#34; my.other.company.ExtClass&#34;一切都按预期工作