Skip to content

Commit 69ed984

Browse files
committed
Merge branch '6.2.x'
2 parents ce81500 + ad949a7 commit 69ed984

File tree

4 files changed

+101
-25
lines changed

4 files changed

+101
-25
lines changed

Diff for: spring-beans/src/main/java/org/springframework/beans/factory/ObjectProvider.java

+39-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ default Stream<T> orderedStream() {
273273
* @see #orderedStream(Predicate)
274274
*/
275275
default Stream<T> stream(Predicate<Class<?>> customFilter) {
276-
return stream().filter(obj -> customFilter.test(obj.getClass()));
276+
return stream(customFilter, true);
277277
}
278278

279279
/**
@@ -287,6 +287,44 @@ default Stream<T> stream(Predicate<Class<?>> customFilter) {
287287
* @see #stream(Predicate)
288288
*/
289289
default Stream<T> orderedStream(Predicate<Class<?>> customFilter) {
290+
return orderedStream(customFilter, true);
291+
}
292+
293+
/**
294+
* Return a custom-filtered {@link Stream} over all matching object instances,
295+
* without specific ordering guarantees (but typically in registration order).
296+
* @param customFilter a custom type filter for selecting beans among the raw
297+
* bean type matches (or {@link #UNFILTERED} for all raw type matches without
298+
* any default filtering)
299+
* @param includeNonSingletons whether to include prototype or scoped beans too
300+
* or just singletons (also applies to FactoryBeans)
301+
* @since 6.2.5
302+
* @see #stream(Predicate)
303+
* @see #orderedStream(Predicate, boolean)
304+
*/
305+
default Stream<T> stream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
306+
if (!includeNonSingletons) {
307+
throw new UnsupportedOperationException("Only supports includeNonSingletons=true by default");
308+
}
309+
return stream().filter(obj -> customFilter.test(obj.getClass()));
310+
}
311+
312+
/**
313+
* Return a custom-filtered {@link Stream} over all matching object instances,
314+
* pre-ordered according to the factory's common order comparator.
315+
* @param customFilter a custom type filter for selecting beans among the raw
316+
* bean type matches (or {@link #UNFILTERED} for all raw type matches without
317+
* any default filtering)
318+
* @param includeNonSingletons whether to include prototype or scoped beans too
319+
* or just singletons (also applies to FactoryBeans)
320+
* @since 6.2.5
321+
* @see #orderedStream()
322+
* @see #stream(Predicate)
323+
*/
324+
default Stream<T> orderedStream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
325+
if (!includeNonSingletons) {
326+
throw new UnsupportedOperationException("Only supports includeNonSingletons=true by default");
327+
}
290328
return orderedStream().filter(obj -> customFilter.test(obj.getClass()));
291329
}
292330

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

+12-12
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,14 @@ public void ifUnique(Consumer<T> dependencyConsumer) throws BeansException {
476476
@SuppressWarnings("unchecked")
477477
@Override
478478
public Stream<T> stream() {
479-
return Arrays.stream(getBeanNamesForTypedStream(requiredType, allowEagerInit))
479+
return Arrays.stream(beanNamesForStream(requiredType, true, allowEagerInit))
480480
.map(name -> (T) getBean(name))
481481
.filter(bean -> !(bean instanceof NullBean));
482482
}
483483
@SuppressWarnings("unchecked")
484484
@Override
485485
public Stream<T> orderedStream() {
486-
String[] beanNames = getBeanNamesForTypedStream(requiredType, allowEagerInit);
486+
String[] beanNames = beanNamesForStream(requiredType, true, allowEagerInit);
487487
if (beanNames.length == 0) {
488488
return Stream.empty();
489489
}
@@ -499,16 +499,16 @@ public Stream<T> orderedStream() {
499499
}
500500
@SuppressWarnings("unchecked")
501501
@Override
502-
public Stream<T> stream(Predicate<Class<?>> customFilter) {
503-
return Arrays.stream(getBeanNamesForTypedStream(requiredType, allowEagerInit))
502+
public Stream<T> stream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
503+
return Arrays.stream(beanNamesForStream(requiredType, includeNonSingletons, allowEagerInit))
504504
.filter(name -> customFilter.test(getType(name)))
505505
.map(name -> (T) getBean(name))
506506
.filter(bean -> !(bean instanceof NullBean));
507507
}
508508
@SuppressWarnings("unchecked")
509509
@Override
510-
public Stream<T> orderedStream(Predicate<Class<?>> customFilter) {
511-
String[] beanNames = getBeanNamesForTypedStream(requiredType, allowEagerInit);
510+
public Stream<T> orderedStream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
511+
String[] beanNames = beanNamesForStream(requiredType, includeNonSingletons, allowEagerInit);
512512
if (beanNames.length == 0) {
513513
return Stream.empty();
514514
}
@@ -547,8 +547,8 @@ else if (parent != null) {
547547
return null;
548548
}
549549

550-
private String[] getBeanNamesForTypedStream(ResolvableType requiredType, boolean allowEagerInit) {
551-
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, true, allowEagerInit);
550+
private String[] beanNamesForStream(ResolvableType requiredType, boolean includeNonSingletons, boolean allowEagerInit) {
551+
return BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this, requiredType, includeNonSingletons, allowEagerInit);
552552
}
553553

554554
@Override
@@ -2508,17 +2508,17 @@ private Stream<Object> resolveStream(boolean ordered) {
25082508
}
25092509

25102510
@Override
2511-
public Stream<Object> stream(Predicate<Class<?>> customFilter) {
2512-
return Arrays.stream(getBeanNamesForTypedStream(this.descriptor.getResolvableType(), true))
2511+
public Stream<Object> stream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
2512+
return Arrays.stream(beanNamesForStream(this.descriptor.getResolvableType(), includeNonSingletons, true))
25132513
.filter(name -> AutowireUtils.isAutowireCandidate(DefaultListableBeanFactory.this, name))
25142514
.filter(name -> customFilter.test(getType(name)))
25152515
.map(name -> getBean(name))
25162516
.filter(bean -> !(bean instanceof NullBean));
25172517
}
25182518

25192519
@Override
2520-
public Stream<Object> orderedStream(Predicate<Class<?>> customFilter) {
2521-
String[] beanNames = getBeanNamesForTypedStream(this.descriptor.getResolvableType(), true);
2520+
public Stream<Object> orderedStream(Predicate<Class<?>> customFilter, boolean includeNonSingletons) {
2521+
String[] beanNames = beanNamesForStream(this.descriptor.getResolvableType(), includeNonSingletons, true);
25222522
if (beanNames.length == 0) {
25232523
return Stream.empty();
25242524
}

Diff for: spring-beans/src/test/java/org/springframework/beans/factory/DefaultListableBeanFactoryTests.java

+16-10
Original file line numberDiff line numberDiff line change
@@ -1519,34 +1519,34 @@ void orderFromAttribute() {
15191519
bd2.setBeanClass(DerivedTestBean.class);
15201520
bd2.setPropertyValues(new MutablePropertyValues(List.of(new PropertyValue("name", "highest"))));
15211521
bd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.HIGHEST_PRECEDENCE);
1522+
bd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
15221523
lbf.registerBeanDefinition("bean2", bd2);
15231524
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
15241525
.containsExactly("highest", "lowest");
1525-
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED).map(TestBean::getName))
1526-
.containsExactly("highest", "lowest");
15271526
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(clazz -> !DerivedTestBean.class.isAssignableFrom(clazz))
15281527
.map(TestBean::getName)).containsExactly("lowest");
1528+
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED).map(TestBean::getName))
1529+
.containsExactly("highest", "lowest");
1530+
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED, false).map(TestBean::getName))
1531+
.containsExactly("lowest");
15291532
}
15301533

15311534
@Test
1532-
void orderFromAttributeOverrideAnnotation() {
1535+
void orderFromAttributeOverridesAnnotation() {
15331536
lbf.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
15341537
RootBeanDefinition rbd1 = new RootBeanDefinition(LowestPrecedenceTestBeanFactoryBean.class);
15351538
rbd1.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.HIGHEST_PRECEDENCE);
15361539
lbf.registerBeanDefinition("lowestPrecedenceFactory", rbd1);
15371540
RootBeanDefinition rbd2 = new RootBeanDefinition(HighestPrecedenceTestBeanFactoryBean.class);
15381541
rbd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.LOWEST_PRECEDENCE);
1542+
rbd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
15391543
lbf.registerBeanDefinition("highestPrecedenceFactory", rbd2);
1540-
GenericBeanDefinition bd1 = new GenericBeanDefinition();
1541-
bd1.setFactoryBeanName("highestPrecedenceFactory");
1542-
lbf.registerBeanDefinition("bean1", bd1);
1543-
GenericBeanDefinition bd2 = new GenericBeanDefinition();
1544-
bd2.setFactoryBeanName("lowestPrecedenceFactory");
1545-
lbf.registerBeanDefinition("bean2", bd2);
15461544
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
15471545
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean", "fromHighestPrecedenceTestBeanFactoryBean");
15481546
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED).map(TestBean::getName))
15491547
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean", "fromHighestPrecedenceTestBeanFactoryBean");
1548+
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED, false).map(TestBean::getName))
1549+
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean");
15501550
}
15511551

15521552
@Test
@@ -1987,7 +1987,6 @@ void getBeanByTypeInstanceDefinedInParent() {
19871987
void getBeanByTypeInstanceWithAmbiguity() {
19881988
RootBeanDefinition bd1 = createConstructorDependencyBeanDefinition(99);
19891989
RootBeanDefinition bd2 = new RootBeanDefinition(ConstructorDependency.class);
1990-
bd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
19911990
bd2.getConstructorArgumentValues().addGenericArgumentValue("43");
19921991
lbf.registerBeanDefinition("bd1", bd1);
19931992
lbf.registerBeanDefinition("bd2", bd2);
@@ -2028,6 +2027,10 @@ void getBeanByTypeInstanceWithAmbiguity() {
20282027
assertThat(resolved).hasSize(2);
20292028
assertThat(resolved).contains(lbf.getBean("bd1"));
20302029
assertThat(resolved).contains(lbf.getBean("bd2"));
2030+
2031+
resolved = provider.stream(ObjectProvider.UNFILTERED, false).collect(Collectors.toSet());
2032+
assertThat(resolved).hasSize(1);
2033+
assertThat(resolved).contains(lbf.getBean("bd2"));
20312034
}
20322035

20332036
@Test
@@ -2082,6 +2085,9 @@ void getBeanByTypeInstanceWithPrimary() {
20822085
assertThat(resolved).hasSize(2);
20832086
assertThat(resolved).contains(lbf.getBean("bd1"));
20842087
assertThat(resolved).contains(lbf.getBean("bd2"));
2088+
2089+
resolved = provider.stream(ObjectProvider.UNFILTERED, false).collect(Collectors.toSet());
2090+
assertThat(resolved).isEmpty();
20852091
}
20862092

20872093
@Test

Diff for: spring-beans/src/test/java/org/springframework/beans/factory/annotation/AutowiredAnnotationBeanPostProcessorTests.java

+34-2
Original file line numberDiff line numberDiff line change
@@ -1614,6 +1614,10 @@ void objectProviderInjectionWithPrototype() {
16141614
assertThat(testBeans).containsExactly(bf.getBean("testBean1", TestBean.class), bf.getBean("testBean2", TestBean.class));
16151615
testBeans = bean.allTestBeansInOrder();
16161616
assertThat(testBeans).containsExactly(bf.getBean("testBean1", TestBean.class), bf.getBean("testBean2", TestBean.class));
1617+
testBeans = bean.allSingletonBeans();
1618+
assertThat(testBeans).isEmpty();
1619+
testBeans = bean.allSingletonBeansInOrder();
1620+
assertThat(testBeans).isEmpty();
16171621
}
16181622

16191623
@Test
@@ -1648,6 +1652,12 @@ void objectProviderInjectionWithSingletonTarget() {
16481652
testBeans = bean.allTestBeansInOrder();
16491653
assertThat(testBeans).hasSize(1);
16501654
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
1655+
testBeans = bean.allSingletonBeans();
1656+
assertThat(testBeans).hasSize(1);
1657+
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
1658+
testBeans = bean.allSingletonBeansInOrder();
1659+
assertThat(testBeans).hasSize(1);
1660+
assertThat(testBeans).contains(bf.getBean("testBean", TestBean.class));
16511661
}
16521662

16531663
@Test
@@ -1675,6 +1685,10 @@ void objectProviderInjectionWithTargetNotAvailable() {
16751685
assertThat(testBeans).isEmpty();
16761686
testBeans = bean.allTestBeansInOrder();
16771687
assertThat(testBeans).isEmpty();
1688+
testBeans = bean.allSingletonBeans();
1689+
assertThat(testBeans).isEmpty();
1690+
testBeans = bean.allSingletonBeansInOrder();
1691+
assertThat(testBeans).isEmpty();
16781692
}
16791693

16801694
@Test
@@ -1698,6 +1712,8 @@ void objectProviderInjectionWithTargetNotUnique() {
16981712
assertThat(bean.streamTestBeansInOrder()).containsExactly(testBean1, testBean2);
16991713
assertThat(bean.allTestBeans()).containsExactly(testBean1, testBean2);
17001714
assertThat(bean.allTestBeansInOrder()).containsExactly(testBean1, testBean2);
1715+
assertThat(bean.allSingletonBeans()).containsExactly(testBean1, testBean2);
1716+
assertThat(bean.allSingletonBeansInOrder()).containsExactly(testBean1, testBean2);
17011717
}
17021718

17031719
@Test
@@ -1728,6 +1744,8 @@ void objectProviderInjectionWithTargetPrimary() {
17281744
assertThat(bean.streamTestBeansInOrder()).containsExactly(testBean2, testBean1);
17291745
assertThat(bean.allTestBeans()).containsExactly(testBean1, testBean2);
17301746
assertThat(bean.allTestBeansInOrder()).containsExactly(testBean2, testBean1);
1747+
assertThat(bean.allSingletonBeans()).containsExactly(testBean1, testBean2);
1748+
assertThat(bean.allSingletonBeansInOrder()).containsExactly(testBean2, testBean1);
17311749
}
17321750

17331751
@Test
@@ -1739,14 +1757,15 @@ void objectProviderInjectionWithUnresolvedOrderedStream() {
17391757
bf.registerBeanDefinition("testBean1", tb1);
17401758
RootBeanDefinition tb2 = new RootBeanDefinition(TestBeanFactory.class);
17411759
tb2.setFactoryMethodName("newTestBean2");
1742-
tb2.setLazyInit(true);
1760+
tb2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
17431761
bf.registerBeanDefinition("testBean2", tb2);
17441762

17451763
ObjectProviderInjectionBean bean = bf.getBean("annotatedBean", ObjectProviderInjectionBean.class);
17461764
assertThat(bean.streamTestBeansInOrder()).containsExactly(bf.getBean("testBean2", TestBean.class),
17471765
bf.getBean("testBean1", TestBean.class));
17481766
assertThat(bean.allTestBeansInOrder()).containsExactly(bf.getBean("testBean2", TestBean.class),
17491767
bf.getBean("testBean1", TestBean.class));
1768+
assertThat(bean.allSingletonBeansInOrder()).containsExactly(bf.getBean("testBean1", TestBean.class));
17501769
}
17511770

17521771
@Test
@@ -1757,6 +1776,7 @@ void objectProviderInjectionWithNonCandidatesInStream() {
17571776
bf.registerBeanDefinition("testBean1", tb1);
17581777
RootBeanDefinition tb2 = new RootBeanDefinition(TestBeanFactory.class);
17591778
tb2.setFactoryMethodName("newTestBean2");
1779+
tb2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
17601780
bf.registerBeanDefinition("testBean2", tb2);
17611781

17621782
DefaultListableBeanFactory parent = new DefaultListableBeanFactory();
@@ -1789,6 +1809,10 @@ void objectProviderInjectionWithNonCandidatesInStream() {
17891809
bf.getBean("testBean2", TestBean.class), bf.getBean("testBean4", TestBean.class));
17901810
assertThat(bean.allTestBeansInOrder()).containsExactly(bf.getBean("testBean2", TestBean.class),
17911811
bf.getBean("testBean1", TestBean.class), bf.getBean("testBean4", TestBean.class));
1812+
assertThat(bean.allSingletonBeans()).containsExactly(bf.getBean("testBean1", TestBean.class),
1813+
bf.getBean("testBean4", TestBean.class));
1814+
assertThat(bean.allSingletonBeansInOrder()).containsExactly(bf.getBean("testBean1", TestBean.class),
1815+
bf.getBean("testBean4", TestBean.class));
17921816

17931817
Map<String, TestBean> typeMatches = BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, TestBean.class);
17941818
assertThat(typeMatches.remove("testBean3")).isNotNull();
@@ -2370,7 +2394,7 @@ void genericsBasedConstructorInjection() {
23702394
}
23712395

23722396
@Test
2373-
@SuppressWarnings({ "rawtypes", "unchecked" })
2397+
@SuppressWarnings("unchecked")
23742398
void genericsBasedConstructorInjectionWithNonTypedTarget() {
23752399
RootBeanDefinition bd = new RootBeanDefinition(RepositoryConstructorInjectionBean.class);
23762400
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
@@ -3393,6 +3417,14 @@ public List<TestBean> allTestBeans() {
33933417
public List<TestBean> allTestBeansInOrder() {
33943418
return this.testBean.orderedStream(ObjectProvider.UNFILTERED).toList();
33953419
}
3420+
3421+
public List<TestBean> allSingletonBeans() {
3422+
return this.testBean.stream(ObjectProvider.UNFILTERED, false).toList();
3423+
}
3424+
3425+
public List<TestBean> allSingletonBeansInOrder() {
3426+
return this.testBean.orderedStream(ObjectProvider.UNFILTERED, false).toList();
3427+
}
33963428
}
33973429

33983430

0 commit comments

Comments
 (0)