几个bean实现相同的接口

时间:2015-04-28 06:05:30

标签: spring spring-el spring-rabbit

具体用法如下:

    @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);
        });
    }
}

1 个答案:

答案 0 :(得分:1)

您的问题不明确 - 您似乎在混合运行时和初始化时间概念。

例如,"#{@queueNameCreator.createUpdateQueueName(e.c.doSomething())}"在初始化期间会被评估一次 - 从这个表达式中不清楚e是什么,或者来自哪里。

但是,您似乎在消息的有效负载中传递了EMessage<E> rawUpdate。此消息来自队列,因此无法影响队列名称。

也许如果你可以解释你想要做什么而不是你试图做什么,我可以更新这个&#34;回答&#34;可能的解决方案。

编辑

如果您的意思是想在SpEL中引用当前(监听器)bean中的某个字段,那么就无法直接完成。

<强> EDIT2

我无法想到在SpEL表达式中获取对当前bean的引用的任何方法 - 它必须是一个常量;这就是注释在Java中的工作方式;他们与阶级联系在一起,而不是实例。

我认为要做你想做的事,你需要恢复使用programmatic endpoint registration。但是,您需要连接MethodRabbitListenerEndpoint(而不是SimpleRabbitListenerEndpoint)以获得您正在寻找的注释(@Header等)的好处。

我们在文档中并没有真正涵盖它;它有点高级,但实质上,你需要注入bean和Method(对于监听器)和DefaultMessageHandlerMethodFactory