什么是SPI
SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制。SPI是一种动态替换发现的机制, 比如有个接口,想运行时动态的给它添加实现,你只需要添加一个实现。我们经常遇到的就是java.sql.Driver接口,其他不同厂商可以针对同一接口做出不同的实现,mysql和postgresql都有不同的实现提供给用户,而Java的SPI机制可以为某个接口寻找服务实现。
简单示例
SPI接口
public interface ObjectSerializer {
byte[] serialize(Object obj) throws ObjectSerializerException;
<T> T deSerialize(byte[] param, Class<T> clazz) throws ObjectSerializerException;
String getSchemeName();
}
SPI具体实现
public class KryoSerializer implements ObjectSerializer {
@Override
public byte[] serialize(Object obj) throws ObjectSerializerException {
byte[] bytes;
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
//获取kryo对象
Kryo kryo = new Kryo();
Output output = new Output(outputStream);
kryo.writeObject(output, obj);
bytes = output.toBytes();
output.flush();
} catch (Exception ex) {
throw new ObjectSerializerException("kryo serialize error" + ex.getMessage());
} finally {
try {
outputStream.flush();
outputStream.close();
} catch (IOException e) {
}
}
return bytes;
}
@Override
public <T> T deSerialize(byte[] param, Class<T> clazz) throws ObjectSerializerException {
T object;
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(param)) {
Kryo kryo = new Kryo();
Input input = new Input(inputStream);
object = kryo.readObject(input, clazz);
input.close();
} catch (Exception e) {
throw new ObjectSerializerException("kryo deSerialize error" + e.getMessage());
}
return object;
}
@Override
public String getSchemeName() {
return "kryoSerializer";
}
}
public class JavaSerializer implements ObjectSerializer {
@Override
public byte[] serialize(Object obj) throws ObjectSerializerException {
ByteArrayOutputStream arrayOutputStream;
try {
arrayOutputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = new ObjectOutputStream(arrayOutputStream);
objectOutput.writeObject(obj);
objectOutput.flush();
objectOutput.close();
} catch (IOException e) {
throw new ObjectSerializerException("JAVA serialize error " + e.getMessage());
}
return arrayOutputStream.toByteArray();
}
@Override
public <T> T deSerialize(byte[] param, Class<T> clazz) throws ObjectSerializerException {
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(param);
try {
ObjectInput input = new ObjectInputStream(arrayInputStream);
return (T) input.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new ObjectSerializerException("JAVA deSerialize error " + e.getMessage());
}
}
@Override
public String getSchemeName() {
return "javaSerializer";
}
}
增加META-INF目录文件
Resource下面创建META-INF/services 目录里创建一个以服务接口命名的文件com.skipper.ObjectSerializer
内容为
com.skipper.KryoSerializer
com.skipper.JavaSerializer
Service类
@Service
public class SerializerService {
public ObjectSerializer getObjectSerializer() {
ServiceLoader<ObjectSerializer> serializers = ServiceLoader.load(ObjectSerializer.class);
final Optional<ObjectSerializer> serializer = StreamSupport.stream(serializers.spliterator(), false)
.findFirst();
return serializer.orElse(new JavaSerializer());
}
}
测试类
@Autowired
private SerializerService serializerService;
@Test
public void serializerTest() throws ObjectSerializerException {
ObjectSerializer objectSerializer = serializerService.getObjectSerializer();
System.out.println(objectSerializer.getSchemeName());
byte[] arrays = objectSerializer.serialize(Arrays.asList("1", "2", "3"));
ArrayList list = objectSerializer.deSerialize(arrays, ArrayList.class);
Assert.assertArrayEquals(Arrays.asList("1", "2", "3").toArray(), list.toArray());
}
结果为 kryoSerializer
网友评论