Java carrega dinamicamente o plugin

Eu quero fazer um aplicativo que possa carregar dinamicamente plug-ins, mas não encontrei nenhuma literatura sobre Internet.

O difícil é que não sei o nome antecipadamente.

Por exemplo, eu tenho uma interface Plugin :

public interface Plugin { public static Plugin newPlugin(); public void executePlugin(String args[]); } 

Para que todos os Plugins de implementação de class no arquivo jar sejam instanciados em uma lista:

 Method method = classToLoad.getMethod ("newPlugin"); mylist.add(method.invoke(null); 
  1. O primeiro problema é que não posso ter um método estático em uma interface.
  2. O segundo problema é que eu não sei como encontrar todas as classs que implementam uma interface

Obrigado pela ajuda.

Portanto, parece que você deseja descobrir dinamicamente Classes que implementam uma interface específica (por exemplo, Plugin ) em tempo de execução. Você tem basicamente duas opções para isso:

  1. Use uma estrutura de componentes como osgi
  2. Use o processo de descoberta interna do Java ( ServiceLoader )

Como há muitos bons tutoriais sobre osgi (também pequenos), não vou detalhar isso aqui. Para usar o processo de descoberta interna do Java, você precisa fazer o seguinte:

  • Agrupar todas as classs “novas” que você deseja descobrir em um arquivo jar
  • Crie um novo arquivo dentro do arquivo jar: META-INF/services/package.Plugin Você deve usar o qualificador de pacote completo aqui
  • Este arquivo é um arquivo de texto simples e contém o nome completo de cada class que implementa o Plugin nesse arquivo jar.
  • Coloque esse arquivo jar no caminho de class do seu aplicativo (potencialmente já em execução)
  • Descubra os serviços:

A descoberta de serviço é feita assim:

 ServiceLoader loader = ServiceLoader.load(Plugin.class) for (Plugin p : loader) { // do something with the plugin } 

Há mais detalhes aqui: http://docs.oracle.com/javase/7/docs/api/java/util/ServiceLoader.html

Quanto aos methods estáticos nas interfaces: não é possível. A semântica disso também seria um pouco estranha, pois os methods estáticos são acessíveis sem uma instância de uma class, e as interfaces apenas definem os methods, sem qualquer funcionalidade. Assim, a estática permitiria chamar Interface.doSomething() enquanto a interface não define nenhuma funcionalidade, isso leva apenas à confusão.

editar:

descrição adicionada o que deve estar no meta-arquivo

Em relação ao seu primeiro problema, não sendo capaz de ter methods estáticos na interface, minha sugestão é simplesmente usar a interface com um marcador e instanciá-lo.

Você é a interface do plugin pode ser simplesmente:

 public interface Plugin { public void executePlugin(String args[]); } 

E então você pode fazer:

 if (someClass instanceOf Plugin) { mylist.add(someClass.newInstance()); } 

Isso leva à segunda pergunta, como você obterá a referência someClass . Não existe uma maneira padrão de encontrar todas as classs implementando uma determinada interface em seu classpath , embora uma abordagem que você possa fazer seja escanear os flasks em seu classpath, se um determinado arquivo terminar com .class determine seu nome completo por seu caminho dentro do caminho de class. jar e use o método Class.forName() para materializar a class.

Em pseudocódigo algo como isto:

 for each jar in your classpath { for each file in JarFile { if (file ends with .class) { materialize class using Class.forName } } } 

Com a instância de Class você pode verificar se está implementando sua interface Plugin .

Também tenha em mente que se você precisar adicionar qualquer contexto aos seus plugins, você pode criar um construtor em cada plugin que recebe seu object de contexto, ao invés de ter o construtor padrão. Nesse caso, em vez de usar newInstance() você teria que obter o construtor com os argumentos desejados por meio de reflection.

    Intereting Posts