1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.springframework.messaging.handler.invocation;
17
18 import io.github.rose.core.util.StringPool;
19 import io.github.rose.mybatis.tenant.util.TenantContextHolder;
20 import io.github.rose.mybatis.tenant.util.TenantUtils;
21 import org.springframework.core.DefaultParameterNameDiscoverer;
22 import org.springframework.core.MethodParameter;
23 import org.springframework.core.ParameterNameDiscoverer;
24 import org.springframework.core.ResolvableType;
25 import org.springframework.lang.Nullable;
26 import org.springframework.messaging.Message;
27 import org.springframework.messaging.handler.HandlerMethod;
28 import org.springframework.util.ObjectUtils;
29
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
32 import java.lang.reflect.Type;
33 import java.nio.charset.StandardCharsets;
34 import java.util.Arrays;
35 import java.util.Objects;
36
37 import static io.github.rose.core.util.Constants.HEADER_TENANT_ID;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class InvocableHandlerMethod extends HandlerMethod {
53
54 private static final Object[] EMPTY_ARGS = new Object[0];
55
56 private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
57
58 private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
59
60
61
62
63 public InvocableHandlerMethod(HandlerMethod handlerMethod) {
64 super(handlerMethod);
65 }
66
67
68
69
70 public InvocableHandlerMethod(Object bean, Method method) {
71 super(bean, method);
72 }
73
74
75
76
77
78
79
80
81
82
83 public InvocableHandlerMethod(Object bean, String methodName, Class<?>... parameterTypes)
84 throws NoSuchMethodException {
85
86 super(bean, methodName, parameterTypes);
87 }
88
89
90
91
92
93 public void setMessageMethodArgumentResolvers(HandlerMethodArgumentResolverComposite argumentResolvers) {
94 this.resolvers = argumentResolvers;
95 }
96
97
98
99
100
101
102
103 public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
104 this.parameterNameDiscoverer = parameterNameDiscoverer;
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 @Nullable
127 public Object invoke(Message<?> message, Object... providedArgs) throws Exception {
128 Object[] args = getMethodArgumentValues(message, providedArgs);
129 if (logger.isTraceEnabled()) {
130 logger.trace("Arguments: " + Arrays.toString(args));
131 }
132
133
134 String tenantId = parseTenantId(message);
135
136 return TenantUtils.execute(tenantId, () -> doInvoke(args));
137 }
138
139 private String parseTenantId(Message<?> message) {
140 Object tenantId = message.getHeaders().get(HEADER_TENANT_ID);
141 if (tenantId == null) {
142 return StringPool.UNKNOWN;
143 }
144 if (tenantId instanceof Long) {
145 return String.valueOf(tenantId);
146 }
147 if (tenantId instanceof Number) {
148 return String.valueOf(tenantId);
149 }
150 if (tenantId instanceof String) {
151 return (String) tenantId;
152 }
153 if (tenantId instanceof byte[]) {
154 return new String((byte[]) tenantId, StandardCharsets.UTF_8);
155 }
156 throw new IllegalArgumentException("未知的数据类型:" + tenantId);
157 }
158
159
160
161
162
163
164
165
166
167 protected Object[] getMethodArgumentValues(Message<?> message, Object... providedArgs) throws Exception {
168 MethodParameter[] parameters = getMethodParameters();
169 if (ObjectUtils.isEmpty(parameters)) {
170 return EMPTY_ARGS;
171 }
172
173 Object[] args = new Object[parameters.length];
174 for (int i = 0; i < parameters.length; i++) {
175 MethodParameter parameter = parameters[i];
176 parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
177 args[i] = findProvidedArgument(parameter, providedArgs);
178 if (args[i] != null) {
179 continue;
180 }
181 if (!this.resolvers.supportsParameter(parameter)) {
182 throw new MethodArgumentResolutionException(
183 message, parameter, formatArgumentError(parameter, "No suitable resolver"));
184 }
185 try {
186 args[i] = this.resolvers.resolveArgument(parameter, message);
187 } catch (Exception ex) {
188
189
190 if (logger.isDebugEnabled()) {
191 String exMsg = ex.getMessage();
192 if (exMsg != null
193 && !exMsg.contains(parameter.getExecutable().toGenericString())) {
194 logger.debug(formatArgumentError(parameter, exMsg));
195 }
196 }
197 throw ex;
198 }
199 }
200 return args;
201 }
202
203
204
205
206 @Nullable
207 protected Object doInvoke(Object... args) throws Exception {
208 try {
209 return getBridgedMethod().invoke(getBean(), args);
210 } catch (IllegalArgumentException ex) {
211 assertTargetBean(getBridgedMethod(), getBean(), args);
212 String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
213 throw new IllegalStateException(formatInvokeError(text, args), ex);
214 } catch (InvocationTargetException ex) {
215
216 Throwable targetException = ex.getTargetException();
217 if (targetException instanceof RuntimeException) {
218 throw (RuntimeException) targetException;
219 } else if (targetException instanceof Error) {
220 throw (Error) targetException;
221 } else if (targetException instanceof Exception) {
222 throw (Exception) targetException;
223 } else {
224 throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
225 }
226 }
227 }
228
229 MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
230 return new AsyncResultMethodParameter(returnValue);
231 }
232
233 private class AsyncResultMethodParameter extends HandlerMethodParameter {
234
235 @Nullable
236 private final Object returnValue;
237
238 private final ResolvableType returnType;
239
240 public AsyncResultMethodParameter(@Nullable Object returnValue) {
241 super(-1);
242 this.returnValue = returnValue;
243 this.returnType =
244 ResolvableType.forType(super.getGenericParameterType()).getGeneric();
245 }
246
247 protected AsyncResultMethodParameter(AsyncResultMethodParameter original) {
248 super(original);
249 this.returnValue = original.returnValue;
250 this.returnType = original.returnType;
251 }
252
253 @Override
254 public Class<?> getParameterType() {
255 if (this.returnValue != null) {
256 return this.returnValue.getClass();
257 }
258 if (!ResolvableType.NONE.equals(this.returnType)) {
259 return this.returnType.toClass();
260 }
261 return super.getParameterType();
262 }
263
264 @Override
265 public Type getGenericParameterType() {
266 return this.returnType.getType();
267 }
268
269 @Override
270 public boolean equals(Object o) {
271 if (o == null || getClass() != o.getClass()) return false;
272 if (!super.equals(o)) return false;
273 AsyncResultMethodParameter that = (AsyncResultMethodParameter) o;
274 return Objects.equals(returnValue, that.returnValue) && Objects.equals(returnType, that.returnType);
275 }
276
277 @Override
278 public int hashCode() {
279 return Objects.hash(super.hashCode(), returnValue, returnType);
280 }
281 }
282 }