2017-01-07 12 views
0

두 프로젝트 (코어 및)가있는 다중 모듈 프로젝트가 있습니다. 아이디어는 코어가 시작될 때마다 A를 실행/실행하는 것입니다.ServiceLoader가 Plugin Jar를 찾는 위치를 사용자 지정하는 방법

ServiceLoader를 찾아보고 플러그인 모듈 폴더에서 코어를 검색하고 호출하도록 사용자 정의 할 수 있습니까?

plugin-Project 
    + Core 
     + src\main\java 
      Core.java 

    + A 
     + src\main\java 
      A.java 

    + Plugins 

코어

public class Core extends Application { 

    private ServiceLoader<View> views; 
    private BorderPane mainBorderPane; 

    @Override 
    public void init() { 
     loadViews(); 
    } 

    private void loadViews() { 
     views = ServiceLoader.load(View.class); 
    } 

    @Override 
    public void start(Stage stage) throws Exception { 
     stage.setTitle("Ui Application"); 

     mainBorderPane = new BorderPane(); 
     mainBorderPane.setTop(createMenuBar()); 

     Scene scene = new Scene(new Group(), 800, 605); 
     scene.setRoot(mainBorderPane); 

     stage.setScene(scene); 
     stage.show(); 
    } 

    private MenuBar createMenuBar() { 
     MenuBar menuBar = new MenuBar(); 
     Menu viewMenu = new Menu("Views"); 
     menuBar.getMenus().add(viewMenu); 

     ToggleGroup toggleGroup = new ToggleGroup(); 

     views.forEach(v -> { 
      RadioMenuItem item = new RadioMenuItem(v.getName()); 
      item.setToggleGroup(toggleGroup); 
      item.setOnAction(event -> { 
       Label label = new Label(v.getName()); 
       mainBorderPane.setLeft(label); 
       mainBorderPane.setCenter(v.getView()); 
      }); 
      viewMenu.getItems().add(item); 
     }); 
     return menuBar; 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 

} 

View.java

public interface View { 

    String getName(); 

    Node getView(); 
} 

시나리오

내가 현재 일하고있는 응용 프로그램은 다중 모듈 독립 실행 형 데스크탑 응용 프로그램입니다. 예를 들어, 코어는 왼쪽에 팬이 있습니다 (왼쪽 창). 왼쪽 창은 LeftPane이라는 인터페이스를 구현하는 모든 모듈의 nodes을 수락합니다. LeftPane 인터페이스를 구현합니다. 코어가 실행될 때마다 폴더,이 경우 플러그인을 검색하여 A를 포함한 모든 번들을 자동으로 시작해야합니다. 그러면 A가 왼쪽 패널을 채 웁니다.

답변

1

가장 쉬운 방법은 이미 클래스 경로에 플러그인을 설치하는 것입니다. 그런 다음 ServiceLoader을 통해 인터페이스에 액세스하면됩니다.

또는 특정 위치에서 플러그인 jar 파일을 감지하여 클래스 경로에 추가하는 메커니즘을 제공하십시오. 이것은 까다로운 부분입니다. 이를 수행하는 한 가지 방법은 응용 프로그램에 사용자 정의 ClassLoader을 사용하여 클래스 경로에 jar 파일을 추가하는 것입니다.

내가 내 응용 프로그램에 대한 사용중인 ClassLoader의 비 공개 API에 액세스하는 다른 방법을 선택한

는 : 플러그인 jar 파일을 클래스 패스에있는 경우

private void addFile(File f) throws IOException // URL to your plugin jar file 
{ 
    addURL(f.toURI().toURL()); 
} 

private void addURL(URL u) throws IOException 
{ 
    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); 
    Class sysclass = URLClassLoader.class; 

    try { 
     Method method = sysclass.getDeclaredMethod("addURL", parameters); 
     method.setAccessible(true); 
     method.invoke(sysloader, new Object[] {u}); 
    } catch (Throwable t) { 
     t.printStackTrace(); 
    } 

} 

당신은 노출 된 인터페이스에 액세스 할 수 있습니다 ServiceLoader을 통해 이것을 예를 들어 설명하겠습니다. 다음과 같이 할 수 있습니다 노출되는 인터페이스 : (또한 기본 클래스 될 수 있습니다)

/** 
* Interface to allow plugins to contribute resource reference properties. 
*/ 
public interface IResourcePropertyLoader { 
    /** 
    * Retrieve the base name for the additional text resource. 
    * @return 
    */ 
    String getResourcePropertyBaseName(); 
} 

인터페이스는 핵심 응용 프로그램의 일부입니다. 플러그인에는이 인터페이스를 구현하는 클래스가 있습니다.

다음 해당 인터페이스의 모든 구현에 대한 조회를 수행합니다

ServiceLoader<ITextPropertyLoader> loader = ServiceLoader.load(ITextPropertyLoader.class, ClassLoader.getSystemClassLoader()); 

ServiceLoader 구현 Iterable을, 따라서 모든 구현을 통해 루프 수 :

for (ITextPropertyLoader textProperty : loader) { 
    final String textPropertyBaseName = textProperty.getTextPropertyBaseName(); 
    System.out.println("Found text property with name: " + textPropertyBaseName); 
} 

또한 살펴 Oracles documentation 이것에 이것뿐만 아니라 question

+0

@ Program-Me-Rev는' ServiceLoader'. – hotzst