具体用法如下:
@Slf4j
public class Client<E, Key> {
@Getter @NonNull private final UpdateListener<E, Key> updateListener;
@NonNull private final SubscriptionFactory subscriptionFactory;
@NonNull private final Map<Key, Instant> updatedRegistry = new ConcurrentHashMap<>();
public Client(UpdateListener<E, Key> updateListener,
SubscriptionFactory subscriptionFactory) {
this.updateListener = updateListener;
this.subscriptionFactory = subscriptionFactory;
this.subscriptionFactory.registerSnapshotClient(updateListener);
log.info("Created new snapshot client for entity key [{}], update type [{}] and component qualifier [{}]",
updateListener.getEntityKey(),
updateListener.getOptionalChangeType(),
updateListener.getComponentQualifier());
}
@RabbitListener(queues = {"#{@queueNameCreator.createUpdateQueueName(snapshotClient.getUpdateListener())}",
"#{@queueNameCreator.createSnapshotQueueName(snapshotClient.getUpdateListener())}"})
public void handleMessage(Message<E> rawUpdate, @Header("last_updated") Instant newUpdatedTime) {
...//more code
}
}
每个'Client'实例都有自己的bean id,不会相互冲突。
如何使用SpEl调用获取此对象的确切updateListener?
使用编程方法和注册方法后,我得到以下异常:
Apr 28, 2015 3:22:47 PM org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler handleError
WARNING: Execution of Rabbit message listener failed.
org.springframework.amqp.rabbit.listener.exception.ListenerExecutionFailedException: Listener method 'public void com.everymatrix.om2020.messaging.model.SnapshotClient.handleMessage(org.springframework.messaging.Message<E>,java.time.Instant)' threw exception
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:126)
at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:93)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:756)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:679)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:82)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:167)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1241)
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:660)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1005)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:989)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:82)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1103)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalStateException: No suitable resolver for argument [0] [type=org.springframework.messaging.Message]
完成后,您需要执行以下操作才能实现所需的行为。
@Configuration
@EnableRabbit
public static class OmbeRabbitListenerConfigurer implements RabbitListenerConfigurer {
@Autowired ApplicationContext applicationContext;
@Autowired SnapshotClientQueueNamesCreator snapshotClientQueueNamesCreator;
@Autowired RabbitListenerContainerFactory rabbitListenerContainerFactory;
@Autowired MessageConverter messageConverter;
@Override
public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
final Collection<SnapshotClient> snapshotClients = applicationContext.getBeansOfType(SnapshotClient.class).values();
System.out.println(snapshotClients);
snapshotClients.stream().forEach(bean -> {
final String snapshotQueueName = snapshotClientQueueNamesCreator.createSnapshotQueueName(bean.getUpdateListener());
final String updateQueueName = snapshotClientQueueNamesCreator.createUpdateQueueName(bean.getUpdateListener());
Method method = Stream.of(bean.getClass().getMethods()).filter(x -> x.getName().equals("handleMessage")).findAny().get();
MethodRabbitListenerEndpoint endpoint = new MethodRabbitListenerEndpoint();
final DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
messageHandlerMethodFactory.afterPropertiesSet();
endpoint.setMessageHandlerMethodFactory(messageHandlerMethodFactory);
endpoint.setBean(bean);
endpoint.setMethod(method);
endpoint.setId(snapshotQueueName + ":" + updateQueueName + UUID.randomUUID());
endpoint.setQueueNames(snapshotQueueName, updateQueueName);
endpoint.setExclusive(false);
registrar.registerEndpoint(endpoint, rabbitListenerContainerFactory);
});
}
}
答案 0 :(得分:1)
您的问题不明确 - 您似乎在混合运行时和初始化时间概念。
例如,"#{@queueNameCreator.createUpdateQueueName(e.c.doSomething())}"
在初始化期间会被评估一次 - 从这个表达式中不清楚e
是什么,或者来自哪里。
但是,您似乎在消息的有效负载中传递了E
:Message<E> rawUpdate
。此消息来自队列,因此无法影响队列名称。
也许如果你可以解释你想要做什么而不是你试图做什么,我可以更新这个&#34;回答&#34;可能的解决方案。
编辑:
如果您的意思是想在SpEL中引用当前(监听器)bean中的某个字段,那么就无法直接完成。
<强> EDIT2 强>:
我无法想到在SpEL表达式中获取对当前bean的引用的任何方法 - 它必须是一个常量;这就是注释在Java中的工作方式;他们与阶级联系在一起,而不是实例。
我认为要做你想做的事,你需要恢复使用programmatic endpoint registration。但是,您需要连接MethodRabbitListenerEndpoint
(而不是SimpleRabbitListenerEndpoint
)以获得您正在寻找的注释(@Header
等)的好处。
我们在文档中并没有真正涵盖它;它有点高级,但实质上,你需要注入bean和Method
(对于监听器)和DefaultMessageHandlerMethodFactory
。