Recently saw some of the company's framework and some of the open source framework seen before some of the service discovery and access are using the Java SPI mechanism.
So simply summarize the idea of the Java SPI mechanism.
The full name of the SPI is the service Provider Interface. Ordinary developers may be unfamiliar because this is for vendors or plug-ins. A more detailed description is available in the Java.util.ServiceLoader documentation. The thought is actually the same as "Callback". The idea of "Callback" is that when we invoke the API, we can write a piece of logical code ourselves and pass it into the API, which is invoked within the API at the right time to achieve some degree of customization.
The abstract modules in our system often have many different implementations, such as the program of the log module, the XML parsing module, the JDBC module scheme, etc. Object-oriented design, we generally recommend that the module is based on interface programming between modules do not hard-code implementation classes. Once a specific implementation class is involved in the code, the pluggable principle is violated, and if you need to replace an implementation, you need to modify the code.
This requires a service discovery mechanism in order to realize that the module can not be dynamically specified in the program when it is assembled. The Java SPI provides a mechanism for finding a service implementation for an interface. A bit like the idea of the IOC is to move control of the assembly outside the program, which is particularly important in modular design. the specific conventions of the Java SPI are as follows:
When the provider of the service provides an implementation of the service interface, create a file named after the service interface in the meta-inf/services/directory of the jar package. The file is a concrete implementation class that implements the service interface. When the external program assembles this module, it can find the specific implementation class name through the configuration file in the jar package meta-inf/services/, and load the instantiation to complete the injection of the module.
Based on such a convention, you can find the implementation class of the service interface well, without needing to make it in code.
JDK provides a service implementation lookup of a tool class: Java.util.ServiceLoader
1.common-logging
The first façade interface for the log provided by Apache. Only interfaces, not implemented. The specific scenario is implemented by each provider, and the discovery log provider scans the Meta-inf/services/org.apache.commons.logging.logfactory configuration file to find the log to the business implementation class by reading the contents of the file. As long as our log implementation contains this file, and in the file to develop Logfactory factory interface implementation class can be.
2.jdbc
Before jdbc4.0, developers also needed to load drivers based on class.forname ("xxx"), JDBC4 also based on the SPI mechanism to discover driver providers that could be passed meta-inf/services/ Java.sql.Driver to expose the driver provider by specifying the implementation class in the file.
Typical is collections.sort (list<t> list,comparator< Super T> C) This method, its second parameter is an instance of implementing the comparator interface. We can write a class based on our own collation, implement this interface, and pass in this method, and the method will sort the list according to our rules.
To extend this idea, we use SPI to recreate the above example. The customer writes their collation into a class and packs it into a jar file, which must have a meta-inf directory and a services directory under it with a text file with the name of the interface as its full name:
Java.util.Comparator
[Java] View plain copy--meta-inf--services--java.util.comparator file contains only one line:
[Java] View plain copy Com.company1.ComparatorProvider This line is the full name of the class that you implemented the comparator interface with the following code:
[Java] View plain copy package com.company1; Import Java.util.Comparator; Import Com.mycompany.myapp.MyItem; public class Comparatorprovider implements comparator<myitem>{@Override public int compare (MYIT Em O1, myitem O2) {//According to name sort return O1.getname (). CompareTo (O2.getname ()); After compiling the package, put it in the class path of your main program. Here's your main program:
[java] View plain copy//searches from the Meta-inf directory of all Jars in the Class path, finds the appropriate class, and loads it. private static ServiceLoader<Comparator> serviceloader = serviceloader.load (Comparator.class); public static void main (string[) args) { List<myitem> mylist = new arraylist<myitem> (); mylist.add (New myitem (2, "C", "HHH")); &n