MethodJmsListenerEndpoint.java 7.6 KB
Newer Older
1
/*
J
Juergen Hoeller 已提交
2
 * Copyright 2002-2019 the original author or authors.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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
 *
 *      http://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.jms.config;

import java.lang.reflect.Method;
20
import java.util.Arrays;
21

22 23
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.support.AopUtils;
S
Stephane Nicoll 已提交
24
import org.springframework.beans.factory.BeanFactory;
25
import org.springframework.beans.factory.BeanFactoryAware;
S
Stephane Nicoll 已提交
26
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
27
import org.springframework.beans.factory.config.EmbeddedValueResolver;
28
import org.springframework.core.annotation.AnnotatedElementUtils;
29 30
import org.springframework.jms.listener.MessageListenerContainer;
import org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter;
31
import org.springframework.jms.support.QosSettings;
32
import org.springframework.jms.support.converter.MessageConverter;
33
import org.springframework.jms.support.destination.DestinationResolver;
34
import org.springframework.lang.Nullable;
35
import org.springframework.messaging.handler.annotation.SendTo;
36
import org.springframework.messaging.handler.annotation.support.MessageHandlerMethodFactory;
37
import org.springframework.messaging.handler.invocation.InvocableHandlerMethod;
38
import org.springframework.util.Assert;
39
import org.springframework.util.StringUtils;
40
import org.springframework.util.StringValueResolver;
41 42 43 44 45 46

/**
 * A {@link JmsListenerEndpoint} providing the method to invoke to process
 * an incoming message for this endpoint.
 *
 * @author Stephane Nicoll
47
 * @author Juergen Hoeller
48 49
 * @since 4.1
 */
50
public class MethodJmsListenerEndpoint extends AbstractJmsListenerEndpoint implements BeanFactoryAware {
51

52
	@Nullable
53 54
	private Object bean;

55
	@Nullable
56 57
	private Method method;

58
	@Nullable
59 60
	private Method mostSpecificMethod;

61
	@Nullable
62
	private MessageHandlerMethodFactory messageHandlerMethodFactory;
63

64
	@Nullable
65 66
	private StringValueResolver embeddedValueResolver;

67

68
	/**
69
	 * Set the actual bean instance to invoke this endpoint method on.
70
	 */
71
	public void setBean(@Nullable Object bean) {
72 73 74
		this.bean = bean;
	}

75
	@Nullable
76
	public Object getBean() {
77
		return this.bean;
78 79 80
	}

	/**
81
	 * Set the method to invoke for processing a message managed by this endpoint.
82
	 */
83
	public void setMethod(@Nullable Method method) {
84 85 86
		this.method = method;
	}

87
	@Nullable
88
	public Method getMethod() {
89
		return this.method;
90 91
	}

92 93 94 95 96 97
	/**
	 * Set the most specific method known for this endpoint's declaration.
	 * <p>In case of a proxy, this will be the method on the target class
	 * (if annotated itself, that is, if not just annotated in an interface).
	 * @since 4.2.3
	 */
98
	public void setMostSpecificMethod(@Nullable Method mostSpecificMethod) {
99 100 101
		this.mostSpecificMethod = mostSpecificMethod;
	}

102
	@Nullable
103 104 105 106
	public Method getMostSpecificMethod() {
		if (this.mostSpecificMethod != null) {
			return this.mostSpecificMethod;
		}
107
		Method method = getMethod();
J
Juergen Hoeller 已提交
108 109 110 111 112 113
		if (method != null) {
			Object bean = getBean();
			if (AopUtils.isAopProxy(bean)) {
				Class<?> targetClass = AopProxyUtils.ultimateTargetClass(bean);
				method = AopUtils.getMostSpecificMethod(method, targetClass);
			}
114
		}
J
Juergen Hoeller 已提交
115
		return method;
116 117
	}

118
	/**
119
	 * Set the {@link MessageHandlerMethodFactory} to use to build the
120 121 122
	 * {@link InvocableHandlerMethod} responsible to manage the invocation
	 * of this endpoint.
	 */
123 124
	public void setMessageHandlerMethodFactory(MessageHandlerMethodFactory messageHandlerMethodFactory) {
		this.messageHandlerMethodFactory = messageHandlerMethodFactory;
125 126
	}

S
Stephane Nicoll 已提交
127
	/**
128 129
	 * Set a value resolver for embedded placeholders and expressions.
	 */
130
	public void setEmbeddedValueResolver(@Nullable StringValueResolver embeddedValueResolver) {
131 132 133 134
		this.embeddedValueResolver = embeddedValueResolver;
	}

	/**
J
Juergen Hoeller 已提交
135
	 * Set the {@link BeanFactory} to use to resolve expressions (may be {@code null}).
S
Stephane Nicoll 已提交
136
	 */
137
	@Override
138
	public void setBeanFactory(@Nullable BeanFactory beanFactory) {
139 140 141
		if (this.embeddedValueResolver == null && beanFactory instanceof ConfigurableBeanFactory) {
			this.embeddedValueResolver = new EmbeddedValueResolver((ConfigurableBeanFactory) beanFactory);
		}
S
Stephane Nicoll 已提交
142
	}
143

144

145 146
	@Override
	protected MessagingMessageListenerAdapter createMessageListener(MessageListenerContainer container) {
147 148
		Assert.state(this.messageHandlerMethodFactory != null,
				"Could not create message listener - MessageHandlerMethodFactory not set");
149
		MessagingMessageListenerAdapter messageListener = createMessageListenerInstance();
J
Juergen Hoeller 已提交
150 151 152
		Object bean = getBean();
		Method method = getMethod();
		Assert.state(bean != null && method != null, "No bean+method set on endpoint");
153
		InvocableHandlerMethod invocableHandlerMethod =
J
Juergen Hoeller 已提交
154
				this.messageHandlerMethodFactory.createInvocableHandlerMethod(bean, method);
155
		messageListener.setHandlerMethod(invocableHandlerMethod);
156 157
		String responseDestination = getDefaultResponseDestination();
		if (StringUtils.hasText(responseDestination)) {
158
			if (container.isReplyPubSubDomain()) {
S
Stephane Nicoll 已提交
159
				messageListener.setDefaultResponseTopicName(responseDestination);
160 161
			}
			else {
S
Stephane Nicoll 已提交
162
				messageListener.setDefaultResponseQueueName(responseDestination);
163 164
			}
		}
165 166 167 168
		QosSettings responseQosSettings = container.getReplyQosSettings();
		if (responseQosSettings != null) {
			messageListener.setResponseQosSettings(responseQosSettings);
		}
169 170 171 172
		MessageConverter messageConverter = container.getMessageConverter();
		if (messageConverter != null) {
			messageListener.setMessageConverter(messageConverter);
		}
173 174 175 176
		DestinationResolver destinationResolver = container.getDestinationResolver();
		if (destinationResolver != null) {
			messageListener.setDestinationResolver(destinationResolver);
		}
177 178 179
		return messageListener;
	}

180 181
	/**
	 * Create an empty {@link MessagingMessageListenerAdapter} instance.
182
	 * @return a new {@code MessagingMessageListenerAdapter} or subclass thereof
183 184 185 186 187
	 */
	protected MessagingMessageListenerAdapter createMessageListenerInstance() {
		return new MessagingMessageListenerAdapter();
	}

S
Stephane Nicoll 已提交
188 189 190
	/**
	 * Return the default response destination, if any.
	 */
191
	@Nullable
S
Stephane Nicoll 已提交
192
	protected String getDefaultResponseDestination() {
193
		Method specificMethod = getMostSpecificMethod();
194 195 196
		if (specificMethod == null) {
			return null;
		}
S
Stephane Nicoll 已提交
197
		SendTo ann = getSendTo(specificMethod);
198 199 200
		if (ann != null) {
			Object[] destinations = ann.value();
			if (destinations.length != 1) {
201 202
				throw new IllegalStateException("Invalid @" + SendTo.class.getSimpleName() + " annotation on '" +
						specificMethod + "' one destination must be set (got " + Arrays.toString(destinations) + ")");
203
			}
S
Stephane Nicoll 已提交
204
			return resolve((String) destinations[0]);
205 206 207 208
		}
		return null;
	}

209
	@Nullable
S
Stephane Nicoll 已提交
210
	private SendTo getSendTo(Method specificMethod) {
211 212 213
		SendTo ann = AnnotatedElementUtils.findMergedAnnotation(specificMethod, SendTo.class);
		if (ann == null) {
			ann = AnnotatedElementUtils.findMergedAnnotation(specificMethod.getDeclaringClass(), SendTo.class);
S
Stephane Nicoll 已提交
214
		}
215
		return ann;
S
Stephane Nicoll 已提交
216 217
	}

218
	@Nullable
S
Stephane Nicoll 已提交
219
	private String resolve(String value) {
220
		return (this.embeddedValueResolver != null ? this.embeddedValueResolver.resolveStringValue(value) : value);
S
Stephane Nicoll 已提交
221 222 223
	}


224 225 226
	@Override
	protected StringBuilder getEndpointDescription() {
		return super.getEndpointDescription()
227 228
				.append(" | bean='").append(this.bean).append("'")
				.append(" | method='").append(this.method).append("'");
229 230 231
	}

}