插件在运行时

时间:2017-07-20 00:47:42

标签: java gradle gradle-plugin

我正在为内部公司使用创建自定义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!");
    }

}

2 个答案:

答案 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;一切都按预期工作