INT-3373: Make Messaging Annotations as Meta
JIRA: https://jira.spring.io/browse/INT-3373 Allow messaging annotations to be used as meta annotations.
This commit is contained in:
committed by
Gary Russell
parent
66fe1c74be
commit
18920851d3
@@ -35,7 +35,7 @@ import org.springframework.integration.aggregator.AbstractCorrelatingMessageHand
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Aggregator {
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.lang.annotation.Target;
|
||||
* @author Artem Bilan
|
||||
* @since 2.0
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Filter {
|
||||
|
||||
@@ -46,7 +46,7 @@ import java.lang.annotation.Target;
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
|
||||
@@ -45,7 +45,7 @@ import java.lang.annotation.Target;
|
||||
* @author Artem Bilan
|
||||
* @since 4.0
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
|
||||
@@ -43,7 +43,7 @@ import java.lang.annotation.Target;
|
||||
* @author Mark Fisher
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
|
||||
@@ -41,7 +41,7 @@ import java.lang.annotation.Target;
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
|
||||
@@ -41,7 +41,7 @@ import java.lang.annotation.Target;
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Splitter {
|
||||
|
||||
@@ -48,7 +48,7 @@ public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRe
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
public IntegrationComponentScanRegistrar() {
|
||||
this.componentRegistrars.put(new AnnotationTypeFilter(MessagingGateway.class), new MessagingGatewayRegistrar());
|
||||
this.componentRegistrars.put(new AnnotationTypeFilter(MessagingGateway.class, true), new MessagingGatewayRegistrar());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -58,7 +58,8 @@ public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRe
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
Map<String, Object> componentScan = importingClassMetadata.getAnnotationAttributes("org.springframework.integration.annotation.IntegrationComponentScan");
|
||||
Map<String, Object> componentScan = importingClassMetadata
|
||||
.getAnnotationAttributes("org.springframework.integration.annotation.IntegrationComponentScan");
|
||||
|
||||
Set<String> basePackages = new HashSet<String>();
|
||||
for (String pkg : (String[]) componentScan.get("value")) {
|
||||
@@ -98,7 +99,8 @@ public class IntegrationComponentScanRegistrar implements ImportBeanDefinitionRe
|
||||
for (BeanDefinition candidateComponent : candidateComponents) {
|
||||
if (candidateComponent instanceof AnnotatedBeanDefinition) {
|
||||
for (ImportBeanDefinitionRegistrar importBeanDefinitionRegistrar : componentRegistrars.values()) {
|
||||
importBeanDefinitionRegistrar.registerBeanDefinitions(((AnnotatedBeanDefinition) candidateComponent).getMetadata(), registry);
|
||||
importBeanDefinitionRegistrar.registerBeanDefinitions(((AnnotatedBeanDefinition) candidateComponent).getMetadata(),
|
||||
registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class MessagingGatewayRegistrar implements ImportBeanDefinitionRegistrar
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||
if (importingClassMetadata != null && importingClassMetadata.hasAnnotation(MessagingGateway.class.getName())) {
|
||||
if (importingClassMetadata != null && importingClassMetadata.isAnnotated(MessagingGateway.class.getName())) {
|
||||
Assert.isTrue(importingClassMetadata.isInterface(),
|
||||
"@MessagingGateway can only be specified on an interface");
|
||||
Map<String, Object> annotationAttributes = importingClassMetadata.getAnnotationAttributes(MessagingGateway.class.getName());
|
||||
|
||||
@@ -125,7 +125,13 @@ public class MessagingAnnotationPostProcessor implements BeanPostProcessor, Bean
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation[] annotations = AnnotationUtils.getAnnotations(method);
|
||||
List<Annotation> annotations = new ArrayList<Annotation>();
|
||||
for (Class<? extends Annotation> annotation : postProcessors.keySet()) {
|
||||
Annotation result = AnnotationUtils.getAnnotation(method, annotation);
|
||||
if (result != null) {
|
||||
annotations.add(result);
|
||||
}
|
||||
}
|
||||
for (Annotation annotation : annotations) {
|
||||
MethodAnnotationPostProcessor postProcessor = postProcessors.get(annotation.annotationType());
|
||||
if (postProcessor != null && shouldCreateEndpoint(annotation)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.springframework.integration.config.annotation;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -48,6 +51,7 @@ import org.springframework.messaging.support.GenericMessage;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class MessagingAnnotationPostProcessorTests {
|
||||
|
||||
@@ -157,8 +161,10 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
TestApplicationContext context = TestUtils.createTestApplicationContext();
|
||||
DirectChannel inputChannel = new DirectChannel();
|
||||
QueueChannel outputChannel = new QueueChannel();
|
||||
DirectChannel eventBus = new DirectChannel();
|
||||
context.registerChannel("inputChannel", inputChannel);
|
||||
context.registerChannel("outputChannel", outputChannel);
|
||||
context.registerChannel("eventBus", eventBus);
|
||||
MessagingAnnotationPostProcessor postProcessor = new MessagingAnnotationPostProcessor();
|
||||
postProcessor.setBeanFactory(context.getBeanFactory());
|
||||
postProcessor.afterPropertiesSet();
|
||||
@@ -170,6 +176,10 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
inputChannel.send(message);
|
||||
Message<?> reply = outputChannel.receive(0);
|
||||
assertNotNull(reply);
|
||||
|
||||
eventBus.send(new GenericMessage<String>("foo"));
|
||||
assertTrue(bean.getInvoked());
|
||||
|
||||
context.stop();
|
||||
}
|
||||
|
||||
@@ -353,11 +363,21 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
@MessageEndpoint
|
||||
private static class ServiceActivatorAnnotatedBean {
|
||||
|
||||
public final AtomicBoolean invoked = new AtomicBoolean();
|
||||
|
||||
@ServiceActivator(inputChannel="inputChannel")
|
||||
public String test(String s) {
|
||||
return s + s;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void eventBus(Object payload) {
|
||||
invoked.set(true);
|
||||
}
|
||||
|
||||
public Boolean getInvoked() {
|
||||
return invoked.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -378,4 +398,11 @@ public class MessagingAnnotationPostProcessorTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Target({ ElementType.METHOD })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@ServiceActivator(inputChannel = "eventBus")
|
||||
public static @interface EventHandler {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
@@ -654,7 +658,7 @@ public class EnableIntegrationTests {
|
||||
|
||||
}
|
||||
|
||||
@MessagingGateway(defaultRequestChannel = "gatewayChannel", defaultHeaders = @GatewayHeader(name = "foo", value = "FOO"))
|
||||
@TestMessagingGateway
|
||||
public static interface TestGateway {
|
||||
|
||||
@Gateway(headers = @GatewayHeader(name = "calledMethod", expression = "#gatewayMethod.name"))
|
||||
@@ -662,6 +666,14 @@ public class EnableIntegrationTests {
|
||||
|
||||
}
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@MessagingGateway(defaultRequestChannel = "gatewayChannel",
|
||||
defaultHeaders = @GatewayHeader(name = "foo", value = "FOO"))
|
||||
public static @interface TestMessagingGateway {
|
||||
}
|
||||
|
||||
|
||||
// Error because the annotation is on a class; it must be on an interface
|
||||
// @MessagingGateway(defaultRequestChannel = "gatewayChannel", defaultHeaders = @GatewayHeader(name = "foo", value = "FOO"))
|
||||
// public static class TestGateway2 { }
|
||||
|
||||
Reference in New Issue
Block a user