Brief on SPI
The official java doc is here. A service is an interface or abstract class which defines a contract for a specific functionality. A service provider is an implementation of that service. Java 6 provides a loader for services based on a provider-configuration file. Just as simple.
Steps to put on jobs
- You define an interface or use an existing one which defines the contract of your service.
- You define and implement one or more implementing classes. This classes should have an empty constructor, that is the only requirement.
- You create META-INF/services folder in you jar archive. In that folder you create a file named with the canonical class name of the interface. (as a sample: your.packages.MyInterface). That is the provider-configuration file.
- In the new created file you insert the canonical names of the implementing classes. These classes are the service providers. If you have more implementations, you put them on separate lines. The syntax of this file is the syntax of properties file (put comments prefixed with # for clarity).
What are the usages?
Insert providers for existent services
JDK provides some usefull SPIs already, which you can use them. Going back to the beggining of my article, the java annotation processor is such a SPI service. So, in place of putting "-processor org.aap.processor.AAPProcessor" as a compiler option, we can skip that. Instead, we create META-INF/services folder. In that folder we create a file called "javax.annotation.processing.Processor". In that provider-configuration file we put "org.aap.processor.AAPProcessor". Now it works. For the article go here. Simply by providing this, the runtime at the moment of loading the jar library, will parse providers and use them. Nice and clean.
Obviously we can provide implementation services for other SPIs as well. I mention here just a few like: LoginModule for authentication, sound sample API or better here, java text spi API (by the way, nice feature), and others.
Usage of service providers in an Observer Pattern manner
Implement your own interface for observable (eventually by extending java.util.Observer). Don't need to handle yourself contributions, service loader is here for that. And can handle contributions from the whole class path.
Usage of service providers in a Factory pattern manner
Implement an interface with a getter to discriminate between implementations. On execution time, use service loader to iterate through implementations and find which provider to use.
Conclusion
That's only a starting point for service provider. I found a nice feature brought by Java 6. In fact not only nice, but almost fabulous. An option to extending platform.
No comments:
Post a Comment