Skip to content

Commit 841d9fb

Browse files
committed
Add public method to get bean order on DefaultListableBeanFactory
Closes gh-34712
1 parent c5da405 commit 841d9fb

File tree

4 files changed

+52
-9
lines changed

4 files changed

+52
-9
lines changed

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

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.util.ArrayList;
3030
import java.util.Arrays;
3131
import java.util.Collection;
32+
import java.util.Collections;
3233
import java.util.Comparator;
3334
import java.util.IdentityHashMap;
3435
import java.util.Iterator;
@@ -2315,6 +2316,33 @@ public boolean usesStandardBeanLookup() {
23152316
return (result instanceof Optional<?> optional ? optional : Optional.ofNullable(result));
23162317
}
23172318

2319+
/**
2320+
* Public method to determine the applicable order value for a given bean.
2321+
* <p>This variant implicitly obtains a corresponding bean instance from this factory.
2322+
* @param beanName the name of the bean
2323+
* @return the corresponding order value (default is {@link Ordered#LOWEST_PRECEDENCE})
2324+
* @since 7.0
2325+
* @see #getOrder(String, Object)
2326+
*/
2327+
public int getOrder(String beanName) {
2328+
return getOrder(beanName, getBean(beanName));
2329+
}
2330+
2331+
/**
2332+
* Public method to determine the applicable order value for a given bean.
2333+
* @param beanName the name of the bean
2334+
* @param beanInstance the bean instance to check
2335+
* @return the corresponding order value (default is {@link Ordered#LOWEST_PRECEDENCE})
2336+
* @since 7.0
2337+
* @see #getOrder(String)
2338+
*/
2339+
public int getOrder(String beanName, Object beanInstance) {
2340+
OrderComparator comparator = (getDependencyComparator() instanceof OrderComparator orderComparator ?
2341+
orderComparator : OrderComparator.INSTANCE);
2342+
return comparator.getOrder(beanInstance,
2343+
new FactoryAwareOrderSourceProvider(Collections.singletonMap(beanInstance, beanName)));
2344+
}
2345+
23182346

23192347
@Override
23202348
public String toString() {
@@ -2672,7 +2700,7 @@ public FactoryAwareOrderSourceProvider(Map<Object, String> instancesToBeanNames)
26722700
return null;
26732701
}
26742702
try {
2675-
RootBeanDefinition beanDefinition = (RootBeanDefinition) getMergedBeanDefinition(beanName);
2703+
BeanDefinition beanDefinition = getMergedBeanDefinition(beanName);
26762704
List<Object> sources = new ArrayList<>(3);
26772705
Object orderAttribute = beanDefinition.getAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE);
26782706
if (orderAttribute != null) {
@@ -2684,13 +2712,15 @@ public FactoryAwareOrderSourceProvider(Map<Object, String> instancesToBeanNames)
26842712
AbstractBeanDefinition.ORDER_ATTRIBUTE + "': " + orderAttribute.getClass().getName());
26852713
}
26862714
}
2687-
Method factoryMethod = beanDefinition.getResolvedFactoryMethod();
2688-
if (factoryMethod != null) {
2689-
sources.add(factoryMethod);
2690-
}
2691-
Class<?> targetType = beanDefinition.getTargetType();
2692-
if (targetType != null && targetType != obj.getClass()) {
2693-
sources.add(targetType);
2715+
if (beanDefinition instanceof RootBeanDefinition rootBeanDefinition) {
2716+
Method factoryMethod = rootBeanDefinition.getResolvedFactoryMethod();
2717+
if (factoryMethod != null) {
2718+
sources.add(factoryMethod);
2719+
}
2720+
Class<?> targetType = rootBeanDefinition.getTargetType();
2721+
if (targetType != null && targetType != obj.getClass()) {
2722+
sources.add(targetType);
2723+
}
26942724
}
26952725
return sources.toArray();
26962726
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1542,6 +1542,7 @@ void orderFromAttribute() {
15421542
bd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.HIGHEST_PRECEDENCE);
15431543
bd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
15441544
lbf.registerBeanDefinition("bean2", bd2);
1545+
15451546
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
15461547
.containsExactly("highest", "lowest");
15471548
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(clazz -> !DerivedTestBean.class.isAssignableFrom(clazz))
@@ -1550,6 +1551,9 @@ void orderFromAttribute() {
15501551
.containsExactly("highest", "lowest");
15511552
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED, false).map(TestBean::getName))
15521553
.containsExactly("lowest");
1554+
1555+
assertThat(lbf.getOrder("bean1")).isEqualTo(Ordered.LOWEST_PRECEDENCE);
1556+
assertThat(lbf.getOrder("bean2")).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
15531557
}
15541558

15551559
@Test
@@ -1562,12 +1566,16 @@ void orderFromAttributeOverridesAnnotation() {
15621566
rbd2.setAttribute(AbstractBeanDefinition.ORDER_ATTRIBUTE, Ordered.LOWEST_PRECEDENCE);
15631567
rbd2.setScope(BeanDefinition.SCOPE_PROTOTYPE);
15641568
lbf.registerBeanDefinition("highestPrecedenceFactory", rbd2);
1569+
15651570
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream().map(TestBean::getName))
15661571
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean", "fromHighestPrecedenceTestBeanFactoryBean");
15671572
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED).map(TestBean::getName))
15681573
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean", "fromHighestPrecedenceTestBeanFactoryBean");
15691574
assertThat(lbf.getBeanProvider(TestBean.class).orderedStream(ObjectProvider.UNFILTERED, false).map(TestBean::getName))
15701575
.containsExactly("fromLowestPrecedenceTestBeanFactoryBean");
1576+
1577+
assertThat(lbf.getOrder("lowestPrecedenceFactory")).isEqualTo(Ordered.HIGHEST_PRECEDENCE);
1578+
assertThat(lbf.getOrder("highestPrecedenceFactory")).isEqualTo(Ordered.LOWEST_PRECEDENCE);
15711579
}
15721580

15731581
@Test
@@ -1579,6 +1587,7 @@ void invalidOrderAttribute() {
15791587
GenericBeanDefinition bd2 = new GenericBeanDefinition();
15801588
bd2.setBeanClass(TestBean.class);
15811589
lbf.registerBeanDefinition("bean", bd2);
1590+
15821591
assertThatIllegalStateException()
15831592
.isThrownBy(() -> lbf.getBeanProvider(TestBean.class).orderedStream().collect(Collectors.toList()))
15841593
.withMessageContaining("Invalid value type for attribute");

spring-context/src/test/java/org/springframework/context/annotation/Gh29105Tests.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ void beanProviderWithParentContextReuseOrder() {
4444
Stream<Class<?>> orderedTypes = child.getBeanProvider(MyService.class).orderedStream().map(Object::getClass);
4545
assertThat(orderedTypes).containsExactly(CustomService.class, DefaultService.class);
4646

47+
assertThat(child.getDefaultListableBeanFactory().getOrder("defaultService")).isEqualTo(0);
48+
assertThat(child.getDefaultListableBeanFactory().getOrder("customService")).isEqualTo(-1);
49+
4750
child.close();
4851
parent.close();
4952
}

spring-core/src/main/java/org/springframework/core/OrderComparator.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,9 @@ else if (p2 && !p1) {
9595
* using {@link #findOrder} and falls back to a regular {@link #getOrder(Object)} call.
9696
* @param obj the object to check
9797
* @return the order value, or {@code Ordered.LOWEST_PRECEDENCE} as fallback
98+
* @since 7.0
9899
*/
99-
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
100+
public int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
100101
Integer order = null;
101102
if (obj != null && sourceProvider != null) {
102103
Object orderSource = sourceProvider.getOrderSource(obj);

0 commit comments

Comments
 (0)