1
1
/*
2
- * Copyright 2002-2015 the original author or authors.
2
+ * Copyright 2002-2018 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
22
22
import java .util .HashMap ;
23
23
import java .util .Map ;
24
24
import java .util .Set ;
25
+ import java .util .stream .Collectors ;
25
26
26
27
import org .springframework .core .LocalVariableTableParameterNameDiscoverer ;
27
28
import org .springframework .core .ParameterNameDiscoverer ;
28
29
import org .springframework .core .annotation .AnnotatedElementUtils ;
29
30
import org .springframework .core .annotation .AnnotationUtils ;
31
+ import org .springframework .expression .Expression ;
30
32
import org .springframework .integration .annotation .Publisher ;
31
33
import org .springframework .messaging .handler .annotation .Header ;
32
34
import org .springframework .messaging .handler .annotation .Payload ;
40
42
* @author Mark Fisher
41
43
* @author Artem Bilan
42
44
* @author Gareth Chapman
45
+ *
43
46
* @since 2.0
44
47
*/
45
48
public class MethodAnnotationPublisherMetadataSource implements PublisherMetadataSource {
46
49
50
+ private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer ();
51
+
52
+ private final Map <Method , String > channels = new HashMap <>();
53
+
54
+ private final Map <Method , Expression > payloadExpressions = new HashMap <>();
55
+
56
+ private final Map <Method , Map <String , Expression >> headersExpressions = new HashMap <>();
57
+
47
58
private final Set <Class <? extends Annotation >> annotationTypes ;
48
59
49
60
private volatile String channelAttributeName = "channel" ;
50
61
51
- private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer ();
52
-
53
62
54
63
public MethodAnnotationPublisherMetadataSource () {
55
- this (Collections .< Class <? extends Annotation >> singleton (Publisher .class ));
64
+ this (Collections .singleton (Publisher .class ));
56
65
}
57
66
58
67
public MethodAnnotationPublisherMetadataSource (Set <Class <? extends Annotation >> annotationTypes ) {
@@ -66,66 +75,98 @@ public void setChannelAttributeName(String channelAttributeName) {
66
75
this .channelAttributeName = channelAttributeName ;
67
76
}
68
77
78
+ @ Override
69
79
public String getChannelName (Method method ) {
70
- String channelName = this .getAnnotationValue (method , this .channelAttributeName , String .class );
71
- if (channelName == null ) {
72
- channelName = this .getAnnotationValue (method .getDeclaringClass (), this .channelAttributeName , String .class );
73
- }
74
- return (StringUtils .hasText (channelName ) ? channelName : null );
80
+ return this .channels .computeIfAbsent (method , method1 -> {
81
+ String channelName = getAnnotationValue (method , this .channelAttributeName , String .class );
82
+ if (channelName == null ) {
83
+ channelName = getAnnotationValue (method .getDeclaringClass (), this .channelAttributeName , String .class );
84
+ }
85
+ return StringUtils .hasText (channelName ) ? channelName : null ;
86
+ });
87
+
75
88
}
76
89
77
- public String getPayloadExpression (Method method ) {
78
- String payloadExpression = null ;
79
- Annotation methodPayloadAnnotation = AnnotationUtils .findAnnotation (method , Payload .class );
90
+ @ Override
91
+ public Expression getExpressionForPayload (Method method ) {
92
+ return this .payloadExpressions .computeIfAbsent (method , method1 -> {
93
+ Expression payloadExpression = null ;
94
+ Annotation methodPayloadAnnotation = AnnotationUtils .findAnnotation (method , Payload .class );
80
95
81
- if (methodPayloadAnnotation != null ) {
82
- payloadExpression = getAnnotationValue (methodPayloadAnnotation , null , String .class );
83
- if (!StringUtils .hasText (payloadExpression )) {
84
- payloadExpression = "#" + PublisherMetadataSource .RETURN_VALUE_VARIABLE_NAME ;
96
+ if (methodPayloadAnnotation != null ) {
97
+ String payloadExpressionString = getAnnotationValue (methodPayloadAnnotation , null , String .class );
98
+ if (!StringUtils .hasText (payloadExpressionString )) {
99
+ payloadExpression = RETURN_VALUE_EXPRESSION ;
100
+ }
101
+ else {
102
+ payloadExpression = EXPRESSION_PARSER .parseExpression (payloadExpressionString );
103
+ }
85
104
}
86
- }
87
105
88
- Annotation [][] annotationArray = method .getParameterAnnotations ();
89
- for (int i = 0 ; i < annotationArray .length ; i ++) {
90
- Annotation [] parameterAnnotations = annotationArray [i ];
91
- for (Annotation currentAnnotation : parameterAnnotations ) {
92
- if (Payload .class .equals (currentAnnotation .annotationType ())) {
93
- Assert .state (payloadExpression == null ,
94
- "@Payload can be used at most once on a @Publisher method, " +
95
- "either at method-level or on a single parameter" );
96
- Assert .state ("" .equals (AnnotationUtils .getValue (currentAnnotation )),
97
- "@Payload on a parameter for a @Publisher method may not contain an expression" );
98
- payloadExpression = "#" + PublisherMetadataSource .ARGUMENT_MAP_VARIABLE_NAME + "[" + i + "]" ;
106
+ Annotation [][] annotationArray = method .getParameterAnnotations ();
107
+ for (int i = 0 ; i < annotationArray .length ; i ++) {
108
+ Annotation [] parameterAnnotations = annotationArray [i ];
109
+ for (Annotation currentAnnotation : parameterAnnotations ) {
110
+ if (Payload .class .equals (currentAnnotation .annotationType ())) {
111
+ Assert .state (payloadExpression == null ,
112
+ "@Payload can be used at most once on a @Publisher method, " +
113
+ "either at method-level or on a single parameter" );
114
+
115
+ Assert .state ("" .equals (AnnotationUtils .getValue (currentAnnotation )),
116
+ "@Payload on a parameter for a @Publisher method may not contain an expression" );
117
+
118
+ payloadExpression =
119
+ EXPRESSION_PARSER .parseExpression ("#" + ARGUMENT_MAP_VARIABLE_NAME + "[" + i + "]" );
120
+ }
99
121
}
100
122
}
101
- }
102
- if ( payloadExpression == null
103
- || payloadExpression . contains ( "#" + PublisherMetadataSource . RETURN_VALUE_VARIABLE_NAME )) {
104
- Assert . isTrue (! void . class . equals ( method . getReturnType ()),
105
- "When defining @Publisher on a void-returning method, an explicit payload " +
106
- "expression that does not rely upon a #return value is required." );
107
- }
108
- return payloadExpression ;
123
+ if ( payloadExpression == null ||
124
+ RETURN_VALUE_EXPRESSION . getExpressionString (). equals ( payloadExpression . getExpressionString ())) {
125
+ Assert . isTrue (! void . class . equals ( method . getReturnType ()),
126
+ "When defining @Publisher on a void-returning method, an explicit payload " +
127
+ "expression that does not rely upon a #return value is required." );
128
+ }
129
+ return payloadExpression ;
130
+ }) ;
109
131
}
110
132
111
- public Map <String , String > getHeaderExpressions (Method method ) {
112
- Map <String , String > headerExpressions = new HashMap <String , String >();
113
- String [] parameterNames = this .parameterNameDiscoverer .getParameterNames (method );
114
- Annotation [][] annotationArray = method .getParameterAnnotations ();
115
- for (int i = 0 ; i < annotationArray .length ; i ++) {
116
- Annotation [] parameterAnnotations = annotationArray [i ];
117
- for (Annotation currentAnnotation : parameterAnnotations ) {
118
- if (Header .class .equals (currentAnnotation .annotationType ())) {
119
- String name = getAnnotationValue (currentAnnotation , null , String .class );
120
- if (!StringUtils .hasText (name )) {
121
- name = parameterNames [i ];
133
+ @ Override
134
+ @ Deprecated
135
+ public String getPayloadExpression (Method method ) {
136
+ return getExpressionForPayload (method )
137
+ .getExpressionString ();
138
+ }
139
+
140
+ @ Override
141
+ public Map <String , Expression > getExpressionsForHeaders (Method method ) {
142
+ return this .headersExpressions .computeIfAbsent (method , method1 -> {
143
+ Map <String , Expression > headerExpressions = new HashMap <>();
144
+ String [] parameterNames = this .parameterNameDiscoverer .getParameterNames (method );
145
+ Annotation [][] annotationArray = method .getParameterAnnotations ();
146
+ for (int i = 0 ; i < annotationArray .length ; i ++) {
147
+ Annotation [] parameterAnnotations = annotationArray [i ];
148
+ for (Annotation currentAnnotation : parameterAnnotations ) {
149
+ if (Header .class .equals (currentAnnotation .annotationType ())) {
150
+ String name = getAnnotationValue (currentAnnotation , null , String .class );
151
+ if (!StringUtils .hasText (name )) {
152
+ name = parameterNames [i ];
153
+ }
154
+ headerExpressions .put (name ,
155
+ EXPRESSION_PARSER .parseExpression ("#" + ARGUMENT_MAP_VARIABLE_NAME + "[" + i + "]" ));
122
156
}
123
- headerExpressions .put (name ,
124
- "#" + PublisherMetadataSource .ARGUMENT_MAP_VARIABLE_NAME + "[" + i + "]" );
125
157
}
126
158
}
127
- }
128
- return headerExpressions ;
159
+ return headerExpressions ;
160
+ });
161
+ }
162
+
163
+ @ Override
164
+ @ Deprecated
165
+ public Map <String , String > getHeaderExpressions (Method method ) {
166
+ return getExpressionsForHeaders (method )
167
+ .entrySet ()
168
+ .stream ()
169
+ .collect (Collectors .toMap (Map .Entry ::getKey , e -> e .getValue ().getExpressionString ()));
129
170
}
130
171
131
172
private <T > T getAnnotationValue (Method method , String attributeName , Class <T > expectedType ) {
@@ -137,7 +178,7 @@ private <T> T getAnnotationValue(Method method, String attributeName, Class<T> e
137
178
throw new IllegalStateException (
138
179
"method [" + method + "] contains more than one publisher annotation" );
139
180
}
140
- value = this . getAnnotationValue (annotation , attributeName , expectedType );
181
+ value = getAnnotationValue (annotation , attributeName , expectedType );
141
182
}
142
183
}
143
184
return value ;
@@ -152,7 +193,7 @@ private <T> T getAnnotationValue(Class<?> clazz, String attributeName, Class<T>
152
193
throw new IllegalStateException (
153
194
"class [" + clazz + "] contains more than one publisher annotation" );
154
195
}
155
- value = this . getAnnotationValue (annotation , attributeName , expectedType );
196
+ value = getAnnotationValue (annotation , attributeName , expectedType );
156
197
}
157
198
}
158
199
return value ;
@@ -161,7 +202,7 @@ private <T> T getAnnotationValue(Class<?> clazz, String attributeName, Class<T>
161
202
@ SuppressWarnings ("unchecked" )
162
203
private <T > T getAnnotationValue (Annotation annotation , String attributeName , Class <T > expectedType ) {
163
204
T value = null ;
164
- Object valueAsObject = (attributeName == null ) ? AnnotationUtils .getValue (annotation )
205
+ Object valueAsObject = (attributeName == null ) ? AnnotationUtils .getValue (annotation )
165
206
: AnnotationUtils .getValue (annotation , attributeName );
166
207
if (valueAsObject != null ) {
167
208
if (expectedType .isAssignableFrom (valueAsObject .getClass ())) {
0 commit comments