2017-07-20 41 views
-2

我正在爲公司內部使用創建自定義Gradle插件。它會增加一些任務到項目中,一個任務的行爲可以由插件用戶定製。想法是擁有包含外部類名稱的插件屬性。這個類必須實現適當的接口才能正確使用。插件的任務將實例化這個類的對象並在執行過程中使用它。運行時插件所需的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在運行時插件,所以它找不到它。

下面你可以找到插件和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

OK,因爲總是回答,只要你發佈的問題來了。 需要將managerClass =「ExtClass」更改爲managerClass =「my.other.company.ExtClass」,並且一切按預期工作

2

即使您已經回答了您自己的問題(您也可以接受它),我想添加一個小小的評論:

如果你想提供一個選項來設置你的插件例外類,爲什麼你不讓用戶直接設置類,通過指定Class<?>而不是String? 依賴關係之一中添加的每個類都在build.gradle文件中可用。您還需要指定軟件包,但您也可以像在Java中一樣使用import。另外,Groovy並不希望你使用後綴.class,你可以簡單地將該類設置爲擴展屬性:

import my.other.company.ExtClass 

[...] 

MyInput { 
    managerClass = ExtClass 
} 
+0

感謝您的好建議。更改爲類而不是字符串。此外,這將與測試用例測試一起工作,而我在測試用例的extClass可見性方面存在問題。 – mrzodiak