开发者

How is the Java Service Provide API supposed to work?

开发者 https://www.devze.com 2023-01-31 20:04 出处:网络
It seems like everybody has had an unpleasant brush with the Java Service Provider, that thing you can do with a file named like META-INF/services/com.example.Interface, but that nobody uses except fo

It seems like everybody has had an unpleasant brush with the Java Service Provider, that thing you can do with a file named like META-INF/services/com.example.Interface, but that nobody uses except for trying to load the right XML parser. I'm trying to work with a library that uses the Service Provider API, and trick it so that I can provide some runtime-extended classes (using cglib) that don't actually implement the interface but can be made to do so easily.

Basically, I think the steps I need to perform are:

  1. Create a custom class loader that will respond to getResources(...) and return an "extra" URL
  2. Also have that class loader hook getResourceAsStream(...) to return a list of the classes I am going to manipulate with cglib, when asked for the "extra" resource
  3. Finally, have that class loader load those classes when requested

But here's where I get l开发者_StackOverflow社区ost. For example, when the library tries to determine what implementers are out there, it calls getResources(...) which returns a bunch of URLs. But getResourceAsStream(...) doesn't take URLs, it takes "names". Names which seem to be classpath-relative, and therefore the same everywhere. So META-INF/services/com.example.Interface in has the same "name" as META-INF/services/com.example.Interface in their JAR, right? Except somehow this works with those blasted XML parsers...

Of course, all of this assumes they were smart/kind enough to call ClassLoader.getSystemClassLoader() rather than using ClassLoader.getSystemResources(...), ClassLoader.getSystemResourceAsStream(...), etc., as in the latter case there's no way to hook the ClassLoader and provide the faked file.

I guess in that case I could use BCEL to manipulate the class files when my code is being packaged by Maven, rather than waiting until runtime to do it with cglib?


The idea I described was along the right track. The mistake I made was in thinking that using ClassLoader.getResourceAsStream(..) to access the contents of the URLs. Instead, you should just URL.openStream().

Had I found it before posting, java.util.ServiceLoader (@since 1.6) provides some insight into how to do things correctly.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号