美文网首页
基础积累:Java SPI机制

基础积累:Java SPI机制

作者: skipper_shou | 来源:发表于2021-01-13 10:54 被阅读0次

    什么是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

    相关文章

      网友评论

          本文标题:基础积累:Java SPI机制

          本文链接:https://www.haomeiwen.com/subject/gcqeaktx.html