Come è il servizio Java forniscono API dovrebbe funzionare?
Domanda
Sembra che ognuno ha avuto una spazzola di sgradevole con la rel Java Service Provider , che cosa si può fare con un file denominato come META-INF / services / com.example.Interface, ma che nessuno usi tranne che per cercare di caricare il destro parser XML. Sto cercando di lavorare con una libreria che utilizza l'API Service Provider, e trucco in modo che posso fornire alcune classi di runtime-estesa (utilizzando cglib) che in realtà non implementano l'interfaccia, ma può essere fatto per farlo facilmente.
In sostanza, credo che i passi che devo svolgere sono:
- Crea un caricatore di classe personalizzata che risponda alle getResources (...) e restituire un URL "extra"
- hanno inoltre che getResourceAsStream gancio class loader (...) per restituire un elenco delle classi che sto per manipolare con cglib, quando gli viene chiesto per la risorsa "extra"
- Infine, ha quel carico class loader quelle classi quando richiesto
Ma qui è dove mi perdo. Ad esempio, quando i tentativi di libreria per determinare quali esecutori sono là fuori, si chiama getResources (...), che restituisce un gruppo di URL. Ma getResourceAsStream (...) non prende gli URL, ci vuole "nomi". I nomi che sembrano essere classpath-relativa, e quindi la stessa ovunque. Così META-INF / services / com.example.Interface in ha lo stesso "nome" come META-INF / services / com.example.Interface nella loro JAR, giusto? Tranne in qualche modo questo funziona con quelli sabbiata parser XML ...
Naturalmente, tutto questo presuppone che erano intelligenti / così gentile da chiamare ClassLoader.getSystemClassLoader () piuttosto che utilizzare ClassLoader.getSystemResources (...), ClassLoader.getSystemResourceAsStream (...), ecc, come nel quest'ultimo caso non c'è modo per agganciare il ClassLoader e fornire il file contraffatto.
Credo che in quel caso potrei usare BCEL per manipolare i file di classe quando il mio codice è stato confezionato da Maven, piuttosto che aspettare fino al runtime di farlo con cglib?
Soluzione
L'idea che ho descritto era lungo la strada giusta. L'errore che ho fatto è stato nel pensare che l'uso ClassLoader.getResourceAsStream(..)
per accedere ai contenuti delle URL. Invece, si dovrebbe solo URL.openStream()
.
Se avessi trovato prima di pubblicare, java.util.ServiceLoader
(@SINCE 1.6) fornisce alcune informazioni sul come fare le cose correttamente.