GH-973: Higher order for RabbitListTestBootstrap (#976)

* GH-973: Higher order for RabbitListTestBootstrap

Fixes https://github.com/spring-projects/spring-amqp/issues/973

When we use `@EnableRabbit` and `@RabbitListenerTest` in the same
configuration set, e.g. mixing real `@Configuration` and test one for
`@RabbitListenerTest`, we may end up with the case when `@EnableRabbit`
is processed before `@RabbitListenerTest`, so, `RabbitListenerTestHarness`
bean is not going to appear in the application context.

* Implement a `DeferredImportSelector` with an `@Order` for the
`@EnableRabbit` as well as `RabbitListenerTest` giving higher order to
the `RabbitListenerTestSelector`, so `RabbitListenerTestBootstrap` is
processed and register its `RabbitListenerTestHarness` earlier, than it
is done by the `RabbitBootstrapConfiguration`

**Cherry-pick to 2.1.x**

* * Fix Checkstyle
* Add JavaDocs to new classes
This commit is contained in:
Artem Bilan
2019-04-10 15:09:26 -04:00
committed by Gary Russell
parent ecb5e113fd
commit 24e8048e70
6 changed files with 105 additions and 26 deletions

View File

@@ -30,6 +30,8 @@ import org.springframework.context.annotation.Import;
* {@code @RabbitListener} beans to capture arguments and result (if any).
*
* @author Gary Russell
* @author Artem Bilan
*
* @since 1.6
*
*/
@@ -37,7 +39,7 @@ import org.springframework.context.annotation.Import;
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableRabbit
@Import(RabbitListenerTestBootstrap.class)
@Import(RabbitListenerTestSelector.class)
public @interface RabbitListenerTest {
/**

View File

@@ -16,36 +16,31 @@
package org.springframework.amqp.rabbit.test;
import org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor;
import org.springframework.amqp.rabbit.config.RabbitListenerConfigUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportAware;
import org.springframework.context.annotation.Role;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* Overrides the default BPP with a {@link RabbitListenerTestHarness}.
*
* @author Gary Russell
* @author Artem Bilan
*
* @since 1.6
*
*/
@Configuration
public class RabbitListenerTestBootstrap implements ImportAware {
private AnnotationMetadata importMetadata;
public class RabbitListenerTestBootstrap implements ImportBeanDefinitionRegistrar {
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.importMetadata = importMetadata;
}
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public RabbitListenerAnnotationBeanPostProcessor rabbitListenerAnnotationProcessor() {
return new RabbitListenerTestHarness(this.importMetadata);
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
registry.registerBeanDefinition(RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME,
BeanDefinitionBuilder.rootBeanDefinition(RabbitListenerTestHarness.class)
.addConstructorArgValue(importingClassMetadata)
.getBeanDefinition());
}
}

View File

@@ -114,11 +114,6 @@ public class RabbitListenerTestHarness extends RabbitListenerAnnotationBeanPostP
return (T) this.listeners.get(id);
}
@Override
public int getOrder() {
return super.getOrder() - 100;
}
private static final class CaptureAdvice implements MethodInterceptor {
private final BlockingQueue<InvocationData> invocationData = new LinkedBlockingQueue<>();

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.amqp.rabbit.test;
import org.springframework.amqp.rabbit.annotation.RabbitListenerConfigurationSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.type.AnnotationMetadata;
/**
* A {@link RabbitListenerConfigurationSelector} extension to register
* a {@link RabbitListenerTestBootstrap}, but already with the higher order,
* so the {@link RabbitListenerTestHarness} bean is registered earlier,
* than {@link org.springframework.amqp.rabbit.annotation.RabbitListenerAnnotationBeanPostProcessor}.
*
* @author Artem Bilan
*
* @since 2.1.6
*/
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class RabbitListenerTestSelector extends RabbitListenerConfigurationSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[] { RabbitListenerTestBootstrap.class.getName() };
}
}