2012-11-06 28 views
17

Tôi muốn xây dựng mô-đun plugin có thể được tải bằng ServiceLoader. Điều này đòi hỏi phải thêm một tệp vào thư mục META-INF/services, được đặt tên theo giao diện dịch vụ và chứa đường dẫn đủ điều kiện cho lớp thực hiện nó. Sau đó, bạn có thể tải các dịch vụ này bằng cách gọi ServiceLoader.load().META-INF/dịch vụ trong JAR với Gradle

Dưới đây là ví dụ:

Giả sử chúng tôi muốn cung cấp giao diện plugin có tên org.example.plugins.PluginService. Sau đó chúng tôi cung cấp dịch vụ này trong lớp org.example.plugins.impl.ExamplePlugin.

Nếu chúng tôi muốn có một số loại cơ chế plugin, chúng tôi có thể tạo tệp JAR, chứa tệp triển khai. Tệp JAR này cũng phải chứa tệp META-INF/services/org.example.plugins.PluginService. Tệp này phải chứa một dòng

org.example.plugins.impl.ExamplePlugin 

để kích hoạt ServiceLoader để tìm cách triển khai. Nếu tập tin JAR là trong build path, bạn có thể tải các plugin bằng cách gọi

Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator(); 

iterator Điều đó sẽ cung cấp cho bạn truy cập vào tất cả các plugin quá được tìm thấy bởi các ServiceLoader.

Vì một số lý do Gradle không bao gồm tệp vào thư mục META-INF theo mặc định. Có cách nào để cho JAR kết quả chứa một tệp như vậy không?

Tôi đã tìm thấy phương thức metaInf trong lớp Jar. Nhưng tôi không biết groovy đủ tốt để tự mình tìm ra giải pháp.

+1

Bạn có chắc chắn không? Làm việc tốt cho tôi. Trường hợp bạn đặt tệp này ở đâu chính xác và giao diện 'build.gradle' của bạn như thế nào? – axtavt

+0

Có thư mục 'META-INF' trong thư mục nguồn chính' src/main/java'. Không có gì đặc biệt với kịch bản xây dựng. Nó gần như là một tiêu chuẩn, có chứa một số phụ thuộc bổ sung và một số kho tùy chỉnh. – pvorb

Trả lời

28

Bạn đặt META-INF/services/org.example.plugins.PluginService trong src/main/java, nhưng nó không phải là một nguồn, đó là một tệp tài nguyên, do đó tệp phải được đặt trong thư mục tài nguyên theo quy ước bố cục thư mục Maven, đó là

src/main/resources/META-INF/services/org.example.plugins.PluginService 

Trong trường hợp này mọi thứ sẽ hoạt động ra khỏi hộp.

5

Trong khi đó, tôi đã tìm thấy giải pháp cho vấn đề của mình trong (một phần) similar Question.

Thêm dòng sau vào file gradle.build, giải quyết vấn đề của tôi

jar { 
    from ('./src/main/java') { 
    include 'META-INF/services/org.example.plugins.PluginService' 
    } 
} 

Bây giờ tập tin JAR trông như mong đợi

. 
|- org 
| `- example 
|  `- plugins 
|  `- impl 
|   `- ExamplePlugin.class 
`- META-INF 
    |- MANIFEST.MF 
    `- services 
     `- org.example.plugins.PluginService 
+0

Tôi sẽ không chấp nhận câu trả lời của riêng mình cho bây giờ, bởi vì tôi nghĩ rằng đó chỉ là một cách giải quyết. Giống như @axtavt đã nói ở trên, nó sẽ hoạt động mà không có các dòng này trong 'build.gradle'. – pvorb

0

Nếu bạn tình cờ kế thừa một số mã di sản dựa trên kiến ​​không tuân theo quy ước maven, những điều sau đây có thể hữu ích.

Xác định nguồn của bạn đặt ra để phù hợp với cấu trúc di sản, và bao gồm một dòng như thế này:

include 'META-INF/services/**'

Trong bộ nguồn của bạn. Mẫu này là chung chung và sẽ nhận tất cả các dịch vụ meta inf của bạn.

Ví dụ đầy đủ bên dưới.

sourceSets { 
    main { 
     java { 
      srcDir 'src' 
      exclude '**/Test*.java' 
     } 
     resources { 
      srcDir 'src' 
      include '**/*.xml' 
      include 'META-INF/services/**' 
     } 
    } 
    test { 
     java { 
      srcDir 'src' 
      include '**/Test*.java' 

     } 
     resources { srcDir 'resources' } 
    } 
} 
Các vấn đề liên quan