在做一些组件封装的时候,例如最近接触的基于Redis存储封装的延迟队列消息组件,为了实现组件能够接受来自各种业务方不同的队列消息数据,组件中就可以使用泛型来定义消息主体数据的类型。在消费消息时又需要把序列化后的消息数据反序列化为对应的java类型的对象。
队列消费者功能一般是基于回调机制实现,启动时会把消费监听实例注册进来。如果要在回调消费实例的消费方法时传递反序列化后的消息对象,就需要在延迟队列组件中实现消息的反序列化操作。这里就需要获取消息类型中定义的消息主体数据的泛型类型,然后反序列化为对象类型的对象。
消费者注册时泛型传递
业务消费方在声明消费监听实例时会定义接收的消息主体的类型。例如下面的代码,消费监听方法接受的是一个MsgPo类型的java对象。
consumer.registerConsumerListener(new DelayQueueHandler<MsgPo>() {
@Override
public boolean execute(DelayQueueJob<MsgPo> msgPo) throws Exception {
//执行消息消费逻辑
});
获取消息体的泛型的类型?
可以通过getGenericSuperclass()方法获得超类的类型,如果是一个ParameterizedType接口类型那就是支持泛型的类型。然后可以再通过getActualTypeArguments() 方法获取泛型类型的数组(泛型可以有多个),然后通过数组加数组下标就可以获取到泛型的类型了
private Class tClass;
public void registerConsumerListener(DelayQueueHandler<T> handler) {
Type type = handler.getClass().getGenericSuperclass();
if(type instanceof ParameterizedType){//如果是ParameterizedType类型代表 支持泛型
//第一个泛型的Class类型
tClass = (Class<T>) ((ParameterizedType) type).getActualTypeArguments()[0];
}
}
消费前把消息主体进行反序列化
从Redis中取出序列化后的消息体,然后使用对应的消息类型对消息进行反序列化生成java对象,调用消费方法时就可以把对象数据传给消费方法了。
Object value = redisTemplate.opsForHash().get(key, messageId);
JSONObject.parseObject(json, new TypeReference<DelayQueueJob<T>>(tClass){});
|