Skip to content

Commit 56269d7

Browse files
committed
Merge branch '6.2.x'
2 parents a460231 + 55181fa commit 56269d7

File tree

5 files changed

+153
-28
lines changed

5 files changed

+153
-28
lines changed

spring-beans/src/main/java/org/springframework/beans/factory/support/AbstractBeanFactory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,7 @@ public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuc
514514
* to check whether the bean with the given name matches the specified type. Allow
515515
* additional constraints to be applied to ensure that beans are not created early.
516516
* @param name the name of the bean to query
517-
* @param typeToMatch the type to match against (as a
518-
* {@code ResolvableType})
517+
* @param typeToMatch the type to match against (as a {@code ResolvableType})
519518
* @return {@code true} if the bean type matches, {@code false} if it
520519
* doesn't match or cannot be determined yet
521520
* @throws NoSuchBeanDefinitionException if there is no bean with the given name

spring-beans/src/main/java/org/springframework/beans/factory/support/DefaultListableBeanFactory.java

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.springframework.beans.factory.BeanFactoryUtils;
6161
import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
6262
import org.springframework.beans.factory.CannotLoadBeanClassException;
63+
import org.springframework.beans.factory.FactoryBean;
6364
import org.springframework.beans.factory.InjectionPoint;
6465
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
6566
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
@@ -191,8 +192,8 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
191192
/** Map from bean name to merged BeanDefinitionHolder. */
192193
private final Map<String, BeanDefinitionHolder> mergedBeanDefinitionHolders = new ConcurrentHashMap<>(256);
193194

194-
/** Set of bean definition names with a primary marker. */
195-
private final Set<String> primaryBeanNames = ConcurrentHashMap.newKeySet(16);
195+
/** Map of bean definition names with a primary marker plus corresponding type. */
196+
private final Map<String, Class<?>> primaryBeanNamesWithType = new ConcurrentHashMap<>(16);
196197

197198
/** Map of singleton and non-singleton bean names, keyed by dependency type. */
198199
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
@@ -1024,7 +1025,7 @@ protected boolean isBeanEligibleForMetadataCaching(String beanName) {
10241025
protected void cacheMergedBeanDefinition(RootBeanDefinition mbd, String beanName) {
10251026
super.cacheMergedBeanDefinition(mbd, beanName);
10261027
if (mbd.isPrimary()) {
1027-
this.primaryBeanNames.add(beanName);
1028+
this.primaryBeanNamesWithType.put(beanName, Void.class);
10281029
}
10291030
}
10301031

@@ -1309,7 +1310,7 @@ else if (isConfigurationFrozen()) {
13091310

13101311
// Cache a primary marker for the given bean.
13111312
if (beanDefinition.isPrimary()) {
1312-
this.primaryBeanNames.add(beanName);
1313+
this.primaryBeanNamesWithType.put(beanName, Void.class);
13131314
}
13141315
}
13151316

@@ -1401,7 +1402,7 @@ protected void resetBeanDefinition(String beanName) {
14011402
destroySingleton(beanName);
14021403

14031404
// Remove a cached primary marker for the given bean.
1404-
this.primaryBeanNames.remove(beanName);
1405+
this.primaryBeanNamesWithType.remove(beanName);
14051406

14061407
// Notify all post-processors that the specified bean definition has been reset.
14071408
for (MergedBeanDefinitionPostProcessor processor : getBeanPostProcessorCache().mergedDefinition) {
@@ -1454,9 +1455,18 @@ protected void checkForAliasCircle(String name, String alias) {
14541455
@Override
14551456
protected void addSingleton(String beanName, Object singletonObject) {
14561457
super.addSingleton(beanName, singletonObject);
1458+
14571459
Predicate<Class<?>> filter = (beanType -> beanType != Object.class && beanType.isInstance(singletonObject));
14581460
this.allBeanNamesByType.keySet().removeIf(filter);
14591461
this.singletonBeanNamesByType.keySet().removeIf(filter);
1462+
1463+
if (this.primaryBeanNamesWithType.containsKey(beanName) && singletonObject.getClass() != NullBean.class) {
1464+
Class<?> beanType = (singletonObject instanceof FactoryBean<?> fb ?
1465+
getTypeForFactoryBean(fb) : singletonObject.getClass());
1466+
if (beanType != null) {
1467+
this.primaryBeanNamesWithType.put(beanName, beanType);
1468+
}
1469+
}
14601470
}
14611471

14621472
@Override
@@ -2245,8 +2255,12 @@ private boolean isSelfReference(@Nullable String beanName, @Nullable String cand
22452255
* not matching the given bean name.
22462256
*/
22472257
private boolean hasPrimaryConflict(String beanName, Class<?> dependencyType) {
2248-
for (String candidate : this.primaryBeanNames) {
2249-
if (isTypeMatch(candidate, dependencyType) && !candidate.equals(beanName)) {
2258+
for (Map.Entry<String, Class<?>> candidate : this.primaryBeanNamesWithType.entrySet()) {
2259+
String candidateName = candidate.getKey();
2260+
Class<?> candidateType = candidate.getValue();
2261+
if (!candidateName.equals(beanName) && (candidateType != Void.class ?
2262+
dependencyType.isAssignableFrom(candidateType) : // cached singleton class for primary bean
2263+
isTypeMatch(candidateName, dependencyType))) { // not instantiated yet or not a singleton
22502264
return true;
22512265
}
22522266
}

spring-context/src/test/java/org/springframework/cache/interceptor/CacheOperationExpressionEvaluatorTests.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,6 @@ class CacheOperationExpressionEvaluatorTests {
6060
private final AnnotationCacheOperationSource source = new AnnotationCacheOperationSource();
6161

6262

63-
private Collection<CacheOperation> getOps(String name) {
64-
Method method = ReflectionUtils.findMethod(AnnotatedClass.class, name, Object.class, Object.class);
65-
return this.source.getCacheOperations(method, AnnotatedClass.class);
66-
}
67-
68-
6963
@Test
7064
void testMultipleCachingSource() {
7165
Collection<CacheOperation> ops = getOps("multipleCaching");
@@ -144,6 +138,12 @@ void resolveBeanReference() {
144138
assertThat(value).isEqualTo(String.class.getName());
145139
}
146140

141+
142+
private Collection<CacheOperation> getOps(String name) {
143+
Method method = ReflectionUtils.findMethod(AnnotatedClass.class, name, Object.class, Object.class);
144+
return this.source.getCacheOperations(method, AnnotatedClass.class);
145+
}
146+
147147
private EvaluationContext createEvaluationContext(Object result) {
148148
return createEvaluationContext(result, null);
149149
}

spring-context/src/test/java/org/springframework/cache/interceptor/CachePutEvaluationTests.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ void getAndPut() {
104104
assertThat(this.cache.get(anotherValue + 100).get()).as("Wrong value for @CachePut key").isEqualTo(anotherValue);
105105
}
106106

107+
107108
@Configuration
108109
@EnableCaching
109110
static class Config implements CachingConfigurer {
@@ -121,8 +122,10 @@ public SimpleService simpleService() {
121122

122123
}
123124

125+
124126
@CacheConfig("test")
125127
public static class SimpleService {
128+
126129
private AtomicLong counter = new AtomicLong();
127130

128131
/**
@@ -144,4 +147,5 @@ public Long getAndPut(long id) {
144147
return this.counter.getAndIncrement();
145148
}
146149
}
150+
147151
}

spring-expression/src/main/java/org/springframework/expression/spel/support/StandardEvaluationContext.java

Lines changed: 121 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -122,34 +122,72 @@ public StandardEvaluationContext(@Nullable Object rootObject) {
122122
}
123123

124124

125+
/**
126+
* Specify the default root context object (including a type descriptor)
127+
* against which unqualified properties, methods, etc. should be resolved.
128+
* @param rootObject the root object to use
129+
* @param typeDescriptor a corresponding type descriptor
130+
*/
125131
public void setRootObject(@Nullable Object rootObject, TypeDescriptor typeDescriptor) {
126132
this.rootObject = new TypedValue(rootObject, typeDescriptor);
127133
}
128134

135+
/**
136+
* Specify the default root context object against which unqualified
137+
* properties, methods, etc. should be resolved.
138+
* @param rootObject the root object to use
139+
*/
129140
public void setRootObject(@Nullable Object rootObject) {
130141
this.rootObject = (rootObject != null ? new TypedValue(rootObject) : TypedValue.NULL);
131142
}
132143

144+
/**
145+
* Return the configured default root context object against which unqualified
146+
* properties, methods, etc. should be resolved (can be {@link TypedValue#NULL}).
147+
*/
133148
@Override
134149
public TypedValue getRootObject() {
135150
return this.rootObject;
136151
}
137152

153+
/**
154+
* Set the list of property accessors to use in this evaluation context.
155+
* <p>Replaces any previously configured property accessors.
156+
*/
138157
public void setPropertyAccessors(List<PropertyAccessor> propertyAccessors) {
139158
this.propertyAccessors = propertyAccessors;
140159
}
141160

161+
/**
162+
* Get the list of property accessors configured in this evaluation context.
163+
*/
142164
@Override
143165
public List<PropertyAccessor> getPropertyAccessors() {
144166
return initPropertyAccessors();
145167
}
146168

147-
public void addPropertyAccessor(PropertyAccessor accessor) {
148-
addBeforeDefault(initPropertyAccessors(), accessor);
169+
/**
170+
* Add the supplied property accessor to this evaluation context.
171+
* @param propertyAccessor the property accessor to add
172+
* @see #getPropertyAccessors()
173+
* @see #setPropertyAccessors(List)
174+
* @see #removePropertyAccessor(PropertyAccessor)
175+
*/
176+
public void addPropertyAccessor(PropertyAccessor propertyAccessor) {
177+
addBeforeDefault(initPropertyAccessors(), propertyAccessor);
149178
}
150179

151-
public boolean removePropertyAccessor(PropertyAccessor accessor) {
152-
return initPropertyAccessors().remove(accessor);
180+
/**
181+
* Remove the supplied property accessor from this evaluation context.
182+
* @param propertyAccessor the property accessor to remove
183+
* @return {@code true} if the property accessor was removed, {@code false}
184+
* if the property accessor was not configured in this evaluation context
185+
* @see #getPropertyAccessors()
186+
* @see #setPropertyAccessors(List)
187+
* @see #addPropertyAccessor(PropertyAccessor)
188+
*/
189+
public boolean removePropertyAccessor(PropertyAccessor propertyAccessor) {
190+
return initPropertyAccessors().remove(propertyAccessor);
153191
}
154192

155193
/**
@@ -191,8 +229,8 @@ public void addIndexAccessor(IndexAccessor indexAccessor) {
191229
/**
192230
* Remove the supplied index accessor from this evaluation context.
193231
* @param indexAccessor the index accessor to remove
194-
* @return {@code true} if the index accessor was removed, {@code false} if
195-
* the index accessor was not configured in this evaluation context
232+
* @return {@code true} if the index accessor was removed, {@code false}
233+
* if the index accessor was not configured in this evaluation context
196234
* @since 6.2
197235
* @see #getIndexAccessors()
198236
* @see #setIndexAccessors(List)
@@ -202,44 +240,96 @@ public boolean removeIndexAccessor(IndexAccessor indexAccessor) {
202240
return initIndexAccessors().remove(indexAccessor);
203241
}
204242

243+
/**
244+
* Set the list of constructor resolvers to use in this evaluation context.
245+
* <p>Replaces any previously configured constructor resolvers.
246+
*/
205247
public void setConstructorResolvers(List<ConstructorResolver> constructorResolvers) {
206248
this.constructorResolvers = constructorResolvers;
207249
}
208250

251+
/**
252+
* Get the list of constructor resolvers to use in this evaluation context.
253+
*/
209254
@Override
210255
public List<ConstructorResolver> getConstructorResolvers() {
211256
return initConstructorResolvers();
212257
}
213258

214-
public void addConstructorResolver(ConstructorResolver resolver) {
215-
addBeforeDefault(initConstructorResolvers(), resolver);
259+
/**
260+
* Add the supplied constructor resolver to this evaluation context.
261+
* @param constructorResolver the constructor resolver to add
262+
* @see #getConstructorResolvers()
263+
* @see #setConstructorResolvers(List)
264+
* @see #removeConstructorResolver(ConstructorResolver)
265+
*/
266+
public void addConstructorResolver(ConstructorResolver constructorResolver) {
267+
addBeforeDefault(initConstructorResolvers(), constructorResolver);
216268
}
217269

218-
public boolean removeConstructorResolver(ConstructorResolver resolver) {
219-
return initConstructorResolvers().remove(resolver);
270+
/**
271+
* Remove the supplied constructor resolver from this evaluation context.
272+
* @param constructorResolver the constructor resolver to remove
273+
* @return {@code true} if the constructor resolver was removed, {@code false}
274+
* if the constructor resolver was not configured in this evaluation context
275+
< * @see #getConstructorResolvers()
276+
* @see #setConstructorResolvers(List)
277+
* @see #addConstructorResolver(ConstructorResolver)
278+
*/
279+
public boolean removeConstructorResolver(ConstructorResolver constructorResolver) {
280+
return initConstructorResolvers().remove(constructorResolver);
220281
}
221282

283+
/**
284+
* Set the list of method resolvers to use in this evaluation context.
285+
* <p>Replaces any previously configured method resolvers.
286+
*/
222287
public void setMethodResolvers(List<MethodResolver> methodResolvers) {
223288
this.methodResolvers = methodResolvers;
224289
}
225290

291+
/**
292+
* Get the list of method resolvers to use in this evaluation context.
293+
*/
226294
@Override
227295
public List<MethodResolver> getMethodResolvers() {
228296
return initMethodResolvers();
229297
}
230298

231-
public void addMethodResolver(MethodResolver resolver) {
232-
addBeforeDefault(initMethodResolvers(), resolver);
299+
/**
300+
* Add the supplied method resolver to this evaluation context.
301+
* @param methodResolver the method resolver to add
302+
* @see #getMethodResolvers()
303+
* @see #setMethodResolvers(List)
304+
* @see #removeMethodResolver(MethodResolver)
305+
*/
306+
public void addMethodResolver(MethodResolver methodResolver) {
307+
addBeforeDefault(initMethodResolvers(), methodResolver);
233308
}
234309

310+
/**
311+
* Remove the supplied method resolver from this evaluation context.
312+
* @param methodResolver the method resolver to remove
313+
* @return {@code true} if the method resolver was removed, {@code false}
314+
* if the method resolver was not configured in this evaluation context
315+
* @see #getMethodResolvers()
316+
* @see #setMethodResolvers(List)
317+
* @see #addMethodResolver(MethodResolver)
318+
*/
235319
public boolean removeMethodResolver(MethodResolver methodResolver) {
236320
return initMethodResolvers().remove(methodResolver);
237321
}
238322

239-
public void setBeanResolver(BeanResolver beanResolver) {
323+
/**
324+
* Set the {@link BeanResolver} to use for looking up beans, if any.
325+
*/
326+
public void setBeanResolver(@Nullable BeanResolver beanResolver) {
240327
this.beanResolver = beanResolver;
241328
}
242329

330+
/**
331+
* Get the configured {@link BeanResolver} for looking up beans, if any.
332+
*/
243333
@Override
244334
public @Nullable BeanResolver getBeanResolver() {
245335
return this.beanResolver;
@@ -276,11 +366,17 @@ public TypeLocator getTypeLocator() {
276366
return this.typeLocator;
277367
}
278368

369+
/**
370+
* Set the {@link TypeConverter} for value conversion.
371+
*/
279372
public void setTypeConverter(TypeConverter typeConverter) {
280373
Assert.notNull(typeConverter, "TypeConverter must not be null");
281374
this.typeConverter = typeConverter;
282375
}
283376

377+
/**
378+
* Get the configured {@link TypeConverter} for value conversion.
379+
*/
284380
@Override
285381
public TypeConverter getTypeConverter() {
286382
if (this.typeConverter == null) {
@@ -289,21 +385,33 @@ public TypeConverter getTypeConverter() {
289385
return this.typeConverter;
290386
}
291387

388+
/**
389+
* Set the {@link TypeComparator} for comparing pairs of objects.
390+
*/
292391
public void setTypeComparator(TypeComparator typeComparator) {
293392
Assert.notNull(typeComparator, "TypeComparator must not be null");
294393
this.typeComparator = typeComparator;
295394
}
296395

396+
/**
397+
* Get the configured {@link TypeComparator} for comparing pairs of objects.
398+
*/
297399
@Override
298400
public TypeComparator getTypeComparator() {
299401
return this.typeComparator;
300402
}
301403

404+
/**
405+
* Set the {@link OperatorOverloader} for mathematical operations.
406+
*/
302407
public void setOperatorOverloader(OperatorOverloader operatorOverloader) {
303408
Assert.notNull(operatorOverloader, "OperatorOverloader must not be null");
304409
this.operatorOverloader = operatorOverloader;
305410
}
306411

412+
/**
413+
* Get the configured {@link OperatorOverloader} for mathematical operations.
414+
*/
307415
@Override
308416
public OperatorOverloader getOperatorOverloader() {
309417
return this.operatorOverloader;

0 commit comments

Comments
 (0)