Skip to content

Commit 1a4682e

Browse files
authored
Apply jspecify nullify to core aop & nnotation packages
Related to: #10083 * Remove `voloatile` from the attributes of `SimplePublisherMetadataSource`
1 parent 81fd917 commit 1a4682e

12 files changed

+63
-33
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
/**
22
* Provides annotations for annotation-based configuration.
33
*/
4+
@org.jspecify.annotations.NullMarked
45
package org.springframework.integration.annotation;

spring-integration-core/src/main/java/org/springframework/integration/aop/CompoundTriggerAdvice.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.integration.aop;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.integration.core.MessageSource;
2022
import org.springframework.integration.util.CompoundTrigger;
2123
import org.springframework.messaging.Message;
@@ -56,7 +58,7 @@ public CompoundTriggerAdvice(CompoundTrigger compoundTrigger, Trigger overrideTr
5658
* @return the message or null
5759
*/
5860
@Override
59-
public Message<?> afterReceive(Message<?> result, MessageSource<?> source) {
61+
public @Nullable Message<?> afterReceive(@Nullable Message<?> result, MessageSource<?> source) {
6062
if (result == null) {
6163
this.compoundTrigger.setOverride(this.override);
6264
}

spring-integration-core/src/main/java/org/springframework/integration/aop/MessagePublishingInterceptor.java

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
import java.lang.reflect.Method;
2020
import java.util.HashMap;
2121
import java.util.Map;
22+
import java.util.Objects;
2223

2324
import org.aopalliance.intercept.MethodInterceptor;
2425
import org.aopalliance.intercept.MethodInvocation;
26+
import org.jspecify.annotations.Nullable;
2527

2628
import org.springframework.aop.support.AopUtils;
2729
import org.springframework.beans.BeansException;
@@ -64,12 +66,15 @@ public class MessagePublishingInterceptor implements MethodInterceptor, BeanFact
6466

6567
private final PublisherMetadataSource metadataSource;
6668

69+
@Nullable
6770
private DestinationResolver<MessageChannel> channelResolver;
6871

72+
@SuppressWarnings("NullAway.Init")
6973
private BeanFactory beanFactory;
7074

7175
private MessageBuilderFactory messageBuilderFactory = new DefaultMessageBuilderFactory();
7276

77+
@Nullable
7378
private String defaultChannelName;
7479

7580
private volatile boolean messageBuilderFactorySet;
@@ -85,7 +90,7 @@ public MessagePublishingInterceptor(PublisherMetadataSource metadataSource) {
8590
* @param defaultChannelName the default channel name.
8691
* @since 4.0.3
8792
*/
88-
public void setDefaultChannelName(String defaultChannelName) {
93+
public void setDefaultChannelName(@Nullable String defaultChannelName) {
8994
this.defaultChannelName = defaultChannelName;
9095
}
9196

@@ -100,24 +105,22 @@ public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
100105

101106
protected MessageBuilderFactory getMessageBuilderFactory() {
102107
if (!this.messageBuilderFactorySet) {
103-
if (this.beanFactory != null) {
104-
this.messageBuilderFactory = IntegrationUtils.getMessageBuilderFactory(this.beanFactory);
105-
}
108+
this.messageBuilderFactory = IntegrationUtils.getMessageBuilderFactory(this.beanFactory);
106109
this.messageBuilderFactorySet = true;
107110
}
108111
return this.messageBuilderFactory;
109112
}
110113

111114
@Override
112-
public final Object invoke(MethodInvocation invocation) throws Throwable {
115+
public final @Nullable Object invoke(MethodInvocation invocation) throws Throwable {
113116
initMessagingTemplateIfAny();
114117
StandardEvaluationContext context = ExpressionUtils.createStandardEvaluationContext(this.beanFactory);
115-
Class<?> targetClass = AopUtils.getTargetClass(invocation.getThis());
118+
Class<?> targetClass = AopUtils.getTargetClass(Objects.requireNonNull(invocation.getThis()));
116119
Method method = AopUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
117-
String[] argumentNames = resolveArgumentNames(method);
120+
@Nullable String[] argumentNames = resolveArgumentNames(method);
118121
context.setVariable(PublisherMetadataSource.METHOD_NAME_VARIABLE_NAME, method.getName());
119-
if (invocation.getArguments().length > 0 && argumentNames != null) {
120-
Map<Object, Object> argumentMap = new HashMap<>();
122+
if (invocation.getArguments().length > 0 && argumentNames != null) {
123+
Map<@Nullable Object, @Nullable Object> argumentMap = new HashMap<>();
121124
for (int i = 0; i < argumentNames.length; i++) {
122125
if (invocation.getArguments().length <= i) {
123126
break;
@@ -152,7 +155,7 @@ private void initMessagingTemplateIfAny() {
152155
}
153156
}
154157

155-
private String[] resolveArgumentNames(Method method) {
158+
private @Nullable String @Nullable [] resolveArgumentNames(Method method) {
156159
return this.parameterNameDiscoverer.getParameterNames(method);
157160
}
158161

@@ -187,7 +190,7 @@ private void publishMessage(Method method, StandardEvaluationContext context) {
187190
}
188191
}
189192

190-
private Map<String, Object> evaluateHeaders(Method method, StandardEvaluationContext context) {
193+
private @Nullable Map<String, Object> evaluateHeaders(Method method, StandardEvaluationContext context) {
191194
Map<String, Expression> headerExpressionMap = this.metadataSource.getExpressionsForHeaders(method);
192195
if (headerExpressionMap != null) {
193196
return ExpressionEvalMap.from(headerExpressionMap)

spring-integration-core/src/main/java/org/springframework/integration/aop/MethodAnnotationPublisherMetadataSource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public void setChannelAttributeName(String channelAttributeName) {
8080
}
8181

8282
@Override
83-
public String getChannelName(Method method) {
83+
public @Nullable String getChannelName(Method method) {
8484
return this.channels.computeIfAbsent(method,
8585
method1 -> {
8686
String channelName = getAnnotationValue(method, this.channelAttributeName);
@@ -92,7 +92,7 @@ public String getChannelName(Method method) {
9292
}
9393

9494
@Override
95-
public Expression getExpressionForPayload(Method method) {
95+
public @Nullable Expression getExpressionForPayload(Method method) {
9696
return this.payloadExpressions.computeIfAbsent(method,
9797
method1 -> {
9898
Expression payloadExpression = null;
@@ -141,7 +141,7 @@ public Map<String, Expression> getExpressionsForHeaders(Method method) {
141141
return this.headersExpressions.computeIfAbsent(method,
142142
method1 -> {
143143
Map<String, Expression> headerExpressions = new HashMap<>();
144-
String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);
144+
@Nullable String[] parameterNames = this.parameterNameDiscoverer.getParameterNames(method);
145145
Annotation[][] annotationArray = method.getParameterAnnotations();
146146
for (int i = 0; i < annotationArray.length; i++) {
147147
Annotation[] parameterAnnotations = annotationArray[i];

spring-integration-core/src/main/java/org/springframework/integration/aop/MethodNameMappingPublisherMetadataSource.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import java.util.Map;
2222
import java.util.stream.Collectors;
2323

24+
import org.jspecify.annotations.Nullable;
25+
2426
import org.springframework.expression.Expression;
2527
import org.springframework.util.Assert;
2628
import org.springframework.util.PatternMatchUtils;
@@ -66,7 +68,7 @@ public void setChannelMap(Map<String, String> channelMap) {
6668
}
6769

6870
@Override
69-
public Expression getExpressionForPayload(Method method) {
71+
public @Nullable Expression getExpressionForPayload(Method method) {
7072
for (Map.Entry<String, Expression> entry : this.payloadExpressionMap.entrySet()) {
7173
if (PatternMatchUtils.simpleMatch(entry.getKey(), method.getName())) {
7274
return entry.getValue();
@@ -76,7 +78,7 @@ public Expression getExpressionForPayload(Method method) {
7678
}
7779

7880
@Override
79-
public Map<String, Expression> getExpressionsForHeaders(Method method) {
81+
public @Nullable Map<String, Expression> getExpressionsForHeaders(Method method) {
8082
return this.headerExpressionMap
8183
.entrySet()
8284
.stream()
@@ -87,7 +89,7 @@ public Map<String, Expression> getExpressionsForHeaders(Method method) {
8789
}
8890

8991
@Override
90-
public String getChannelName(Method method) {
92+
public @Nullable String getChannelName(Method method) {
9193
for (Map.Entry<String, String> entry : this.channelMap.entrySet()) {
9294
if (PatternMatchUtils.simpleMatch(entry.getKey(), method.getName())) {
9395
return entry.getValue();

spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationAdvisor.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.util.Arrays;
21+
import java.util.Objects;
2122
import java.util.stream.Collectors;
2223

2324
import org.aopalliance.aop.Advice;
25+
import org.jspecify.annotations.Nullable;
2426

2527
import org.springframework.aop.ClassFilter;
2628
import org.springframework.aop.MethodMatcher;
@@ -73,7 +75,7 @@ public PublisherAnnotationAdvisor(Class<? extends Annotation>... publisherAnnota
7375
* @param defaultChannelName the default channel name.
7476
* @since 4.0.3
7577
*/
76-
public void setDefaultChannelName(String defaultChannelName) {
78+
public void setDefaultChannelName(@Nullable String defaultChannelName) {
7779
this.interceptor.setDefaultChannelName(defaultChannelName);
7880
}
7981

@@ -104,7 +106,7 @@ private static Pointcut buildPointcut(Class<? extends Annotation>[] publisherAnn
104106
result.union(cpc).union(mpc);
105107
}
106108
}
107-
return result;
109+
return Objects.requireNonNull(result);
108110
}
109111

110112
private static final class MetaAnnotationMatchingPointcut implements Pointcut {
@@ -133,7 +135,7 @@ private static final class MetaAnnotationMatchingPointcut implements Pointcut {
133135
* (can be <code>null</code>)
134136
*/
135137
MetaAnnotationMatchingPointcut(
136-
Class<? extends Annotation> classAnnotationType, Class<? extends Annotation> methodAnnotationType) {
138+
@Nullable Class<? extends Annotation> classAnnotationType, @Nullable Class<? extends Annotation> methodAnnotationType) {
137139

138140
Assert.isTrue((classAnnotationType != null || methodAnnotationType != null),
139141
"Either Class annotation type or Method annotation type needs to be specified (or both)");

spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherAnnotationBeanPostProcessor.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,22 @@
1616

1717
package org.springframework.integration.aop;
1818

19+
import org.jspecify.annotations.Nullable;
20+
1921
import org.springframework.aop.framework.autoproxy.AbstractBeanFactoryAwareAdvisingPostProcessor;
2022
import org.springframework.beans.factory.BeanCreationException;
2123
import org.springframework.beans.factory.BeanFactory;
2224
import org.springframework.beans.factory.BeanNameAware;
2325
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
2426
import org.springframework.beans.factory.SmartInitializingSingleton;
27+
import org.springframework.util.Assert;
2528

2629
/**
2730
* Post-processes beans that contain the
2831
* method-level @{@link org.springframework.integration.annotation.Publisher} annotation.
2932
* <p>
3033
* Only one bean instance of this processor can be declared in the application context, manual
31-
* or automatic by thr framework via annotation or XML processing.
34+
* or automatic by the framework via annotation or XML processing.
3235
*
3336
* @author Oleg Zhurakousky
3437
* @author Mark Fisher
@@ -42,10 +45,18 @@
4245
public class PublisherAnnotationBeanPostProcessor extends AbstractBeanFactoryAwareAdvisingPostProcessor
4346
implements BeanNameAware, SmartInitializingSingleton {
4447

45-
private String defaultChannelName;
48+
/**
49+
* This value is optional and may be {@code null}, indicating that no default channel
50+
* is configured and message routing must be handled explicitly elsewhere. For example:
51+
* {@link MessagePublishingInterceptor} can accept a null value for this attribute.
52+
*
53+
*/
54+
private @Nullable String defaultChannelName;
4655

56+
@SuppressWarnings("NullAway.Init")
4757
private String beanName;
4858

59+
@SuppressWarnings("NullAway.Init")
4960
private BeanFactory beanFactory;
5061

5162
/**
@@ -60,6 +71,7 @@ public void setDefaultChannelName(String defaultChannelName) {
6071

6172
@Override
6273
public void setBeanName(String name) {
74+
Assert.notNull(name, "'name' must not be null");
6375
this.beanName = name;
6476
}
6577

spring-integration-core/src/main/java/org/springframework/integration/aop/PublisherMetadataSource.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import java.lang.reflect.Method;
2020
import java.util.Map;
2121

22+
import org.jspecify.annotations.Nullable;
23+
2224
import org.springframework.expression.Expression;
2325
import org.springframework.expression.ExpressionParser;
2426
import org.springframework.expression.spel.standard.SpelExpressionParser;
@@ -55,7 +57,7 @@ interface PublisherMetadataSource {
5557
* @param method The Method.
5658
* @return The channel name.
5759
*/
58-
String getChannelName(Method method);
60+
@Nullable String getChannelName(Method method);
5961

6062
/**
6163
* Returns the SpEL expression to be evaluated for creating the Message
@@ -64,7 +66,7 @@ interface PublisherMetadataSource {
6466
* @return rhe payload expression.
6567
* @since 5.0.4
6668
*/
67-
Expression getExpressionForPayload(Method method);
69+
@Nullable Expression getExpressionForPayload(Method method);
6870

6971
/**
7072
* Returns the map of expression strings to be evaluated for any headers
@@ -73,6 +75,6 @@ interface PublisherMetadataSource {
7375
* @param method The Method.
7476
* @return The header expressions.
7577
*/
76-
Map<String, Expression> getExpressionsForHeaders(Method method);
78+
@Nullable Map<String, Expression> getExpressionsForHeaders(Method method);
7779

7880
}

spring-integration-core/src/main/java/org/springframework/integration/aop/SimpleActiveIdleReceiveMessageAdvice.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.time.Duration;
2020

21+
import org.jspecify.annotations.Nullable;
22+
2123
import org.springframework.integration.util.DynamicPeriodicTrigger;
2224
import org.springframework.messaging.Message;
2325
import org.springframework.util.Assert;
@@ -67,7 +69,7 @@ public void setActivePollPeriod(long activePollPeriod) {
6769
}
6870

6971
@Override
70-
public Message<?> afterReceive(Message<?> result, Object source) {
72+
public @Nullable Message<?> afterReceive(@Nullable Message<?> result, Object source) {
7173
if (result == null) {
7274
this.trigger.setDuration(this.idlePollPeriod);
7375
}

spring-integration-core/src/main/java/org/springframework/integration/aop/SimplePublisherMetadataSource.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.Map;
2121
import java.util.stream.Collectors;
2222

23+
import org.jspecify.annotations.Nullable;
24+
2325
import org.springframework.expression.Expression;
2426

2527
/**
@@ -34,18 +36,18 @@
3436
*/
3537
public class SimplePublisherMetadataSource implements PublisherMetadataSource {
3638

37-
private volatile String channelName;
39+
private @Nullable String channelName;
3840

39-
private volatile Expression payloadExpression;
41+
private @Nullable Expression payloadExpression;
4042

41-
private volatile Map<String, Expression> headerExpressions;
43+
private @Nullable Map<String, Expression> headerExpressions;
4244

4345
public void setChannelName(String channelName) {
4446
this.channelName = channelName;
4547
}
4648

4749
@Override
48-
public String getChannelName(Method method) {
50+
public @Nullable String getChannelName(Method method) {
4951
return this.channelName;
5052
}
5153

@@ -54,7 +56,7 @@ public void setPayloadExpression(String payloadExpression) {
5456
}
5557

5658
@Override
57-
public Expression getExpressionForPayload(Method method) {
59+
public @Nullable Expression getExpressionForPayload(Method method) {
5860
return this.payloadExpression;
5961
}
6062

@@ -67,7 +69,7 @@ public void setHeaderExpressions(Map<String, String> headerExpressions) {
6769
}
6870

6971
@Override
70-
public Map<String, Expression> getExpressionsForHeaders(Method method) {
72+
public @Nullable Map<String, Expression> getExpressionsForHeaders(Method method) {
7173
return this.headerExpressions;
7274
}
7375

0 commit comments

Comments
 (0)