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);
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:
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:
META-INF/services/package.Plugin
Você deve usar o qualificador de pacote completo aqui Plugin
nesse arquivo jar. 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.