Nullability fine-tuning around bean properties

Issue: SPR-15720
Issue: SPR-15792
This commit is contained in:
Juergen Hoeller
2017-07-19 11:43:58 +02:00
parent 06fc092be2
commit 9fc4fb10b0
31 changed files with 243 additions and 206 deletions

View File

@@ -232,11 +232,15 @@ public abstract class AbstractMethodMessageHandler<T>
this.returnValueHandlers.addHandlers(initReturnValueHandlers());
}
for (String beanName : this.applicationContext.getBeanNamesForType(Object.class)) {
ApplicationContext context = getApplicationContext();
if (context == null) {
return;
}
for (String beanName : context.getBeanNamesForType(Object.class)) {
if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) {
Class<?> beanType = null;
try {
beanType = this.applicationContext.getType(beanName);
beanType = context.getType(beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
@@ -279,8 +283,15 @@ public abstract class AbstractMethodMessageHandler<T>
* @param handler the handler to check, either an instance of a Spring bean name
*/
protected final void detectHandlerMethods(final Object handler) {
Class<?> handlerType = (handler instanceof String ?
this.applicationContext.getType((String) handler) : handler.getClass());
Class<?> handlerType;
if (handler instanceof String) {
ApplicationContext context = getApplicationContext();
Assert.state(context != null, "ApplicationContext is required for resolving handler bean names");
handlerType = context.getType((String) handler);
}
else {
handlerType = handler.getClass();
}
if (handlerType != null) {
final Class<?> userType = ClassUtils.getUserClass(handlerType);
@@ -338,9 +349,10 @@ public abstract class AbstractMethodMessageHandler<T>
protected HandlerMethod createHandlerMethod(Object handler, Method method) {
HandlerMethod handlerMethod;
if (handler instanceof String) {
ApplicationContext context = getApplicationContext();
Assert.state(context != null, "ApplicationContext is required for resolving handler bean names");
String beanName = (String) handler;
handlerMethod = new HandlerMethod(beanName,
this.applicationContext.getAutowireCapableBeanFactory(), method);
handlerMethod = new HandlerMethod(beanName, context.getAutowireCapableBeanFactory(), method);
}
else {
handlerMethod = new HandlerMethod(handler, method);
@@ -645,7 +657,7 @@ public abstract class AbstractMethodMessageHandler<T>
}
@Override
public void onSuccess(Object result) {
public void onSuccess(@Nullable Object result) {
try {
MethodParameter returnType = this.handlerMethod.getAsyncReturnValueType(result);
returnValueHandlers.handleReturnValue(result, returnType, this.message);

View File

@@ -252,7 +252,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
}
MethodParameter getAsyncReturnValueType(Object returnValue) {
MethodParameter getAsyncReturnValueType(@Nullable Object returnValue) {
return new AsyncResultMethodParameter(returnValue);
}
@@ -264,7 +264,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
private final ResolvableType returnType;
public AsyncResultMethodParameter(Object returnValue) {
public AsyncResultMethodParameter(@Nullable Object returnValue) {
super(-1);
this.returnValue = returnValue;
this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric();

View File

@@ -54,6 +54,7 @@ public class SimpMessagingTemplate extends AbstractMessageSendingTemplate<String
private volatile long sendTimeout = -1;
@Nullable
private MessageHeaderInitializer headerInitializer;

View File

@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.SmartLifecycle;
@@ -305,8 +306,9 @@ public class SimpAnnotationMethodMessageHandler extends AbstractMethodMessageHan
protected List<HandlerMethodArgumentResolver> initArgumentResolvers() {
ConfigurableBeanFactory beanFactory = (getApplicationContext() instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) getApplicationContext()).getBeanFactory() : null);
ApplicationContext context = getApplicationContext();
ConfigurableBeanFactory beanFactory = (context instanceof ConfigurableApplicationContext ?
((ConfigurableApplicationContext) context).getBeanFactory() : null);
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();

View File

@@ -16,8 +16,6 @@
package org.springframework.messaging.support;
import java.util.UUID;
import org.springframework.lang.Nullable;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.IdGenerator;
@@ -31,6 +29,10 @@ import org.springframework.util.IdGenerator;
*/
public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitializer {
private static final IdGenerator ID_VALUE_NONE_GENERATOR = () -> MessageHeaders.ID_VALUE_NONE;
@Nullable
private IdGenerator idGenerator;
private boolean enableTimestamp;
@@ -41,20 +43,12 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
* instances with.
* <p>By default this property is set to {@code null} in which case the default
* IdGenerator of {@link org.springframework.messaging.MessageHeaders} is used.
* <p>To have no id's generated at all, see {@link #setDisableIdGeneration()}.
* <p>To have no ids generated at all, see {@link #setDisableIdGeneration()}.
*/
public void setIdGenerator(@Nullable IdGenerator idGenerator) {
this.idGenerator = idGenerator;
}
/**
* A shortcut for calling {@link #setIdGenerator(org.springframework.util.IdGenerator)}
* with an id generation strategy to disable id generation completely.
*/
public void setDisableIdGeneration() {
this.idGenerator = ID_VALUE_NONE_GENERATOR;
}
/**
* Return the configured {@code IdGenerator}, if any.
*/
@@ -63,6 +57,14 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
return this.idGenerator;
}
/**
* A shortcut for calling {@link #setIdGenerator} with an id generation strategy
* to disable id generation completely.
*/
public void setDisableIdGeneration() {
this.idGenerator = ID_VALUE_NONE_GENERATOR;
}
/**
* Whether to enable the automatic addition of the
* {@link org.springframework.messaging.MessageHeaders#TIMESTAMP} header on
@@ -90,12 +92,4 @@ public class IdTimestampMessageHeaderInitializer implements MessageHeaderInitial
headerAccessor.setEnableTimestamp(isEnableTimestamp());
}
private static final IdGenerator ID_VALUE_NONE_GENERATOR = new IdGenerator() {
@Override
public UUID generateId() {
return MessageHeaders.ID_VALUE_NONE;
}
};
}

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.TimeoutException;
import reactor.core.publisher.Mono;
import reactor.core.publisher.MonoProcessor;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.concurrent.FailureCallback;
import org.springframework.util.concurrent.ListenableFuture;
@@ -67,12 +68,14 @@ abstract class AbstractMonoToListenableFutureAdapter<S, T> implements Listenable
@Override
@Nullable
public T get() throws InterruptedException {
S result = this.monoProcessor.block();
return adapt(result);
}
@Override
@Nullable
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
Assert.notNull(unit, "TimeUnit must not be null");
Duration duration = Duration.ofMillis(TimeUnit.MILLISECONDS.convert(timeout, unit));
@@ -111,6 +114,7 @@ abstract class AbstractMonoToListenableFutureAdapter<S, T> implements Listenable
}
protected abstract T adapt(S result);
@Nullable
protected abstract T adapt(@Nullable S result);
}

View File

@@ -18,6 +18,8 @@ package org.springframework.messaging.tcp.reactor;
import reactor.core.publisher.Mono;
import org.springframework.lang.Nullable;
/**
* A Mono-to-ListenableFuture adapter where the source and the target from
* the Promise and the ListenableFuture respectively are of the same type.
@@ -33,7 +35,7 @@ class MonoToListenableFutureAdapter<T> extends AbstractMonoToListenableFutureAda
}
@Override
protected T adapt(T result) {
protected T adapt(@Nullable T result) {
return result;
}