spring-framework icon indicating copy to clipboard operation
spring-framework copied to clipboard

Add public method to get bean order

Open mhalbritter opened this issue 8 months ago • 4 comments

Hello,

in Boot we have the use-case to get the order of a bean. We have the bean instance, and also the bean name.

We tried:

return new AnnotationAwareOrderComparator() {
	@Override
	public int getOrder(Object obj) {
		return super.getOrder(obj);
	}
}.getOrder(bean);

but this only looks at the bean itself, not the factory method.

Combined with this:

Order orderAnnotation = beanFactory.findAnnotationOnBean(beanName, Order.class);
if (orderAnnotation != null) {
	return orderAnnotation.value();
}

it also supports @Order on the bean method, but it's missing @Priority (is that supported on bean methods?) and, looking at org.springframework.beans.factory.support.DefaultListableBeanFactory.FactoryAwareOrderSourceProvider there's also a ORDER attribute on the bean definition.

There's also org.springframework.core.annotation.OrderUtils but this only looks at annotations, not at implements Ordered.

Would it be possible to provide a way to reliably get the order of the bean?

mhalbritter avatar Apr 03 '25 10:04 mhalbritter

Ordering is semantically rather involved, not only in terms of potential order value sources, but also considering PriorityOrdered versus Ordered which effectively indicates two separate order value ranges in a mixed sort attempt.

So while we could add a int getOrder(beanName) method to DefaultListableBeanFactory, it would come with the limitation of not differentiating between priority order and regular order. Also, it would just work against singletons, otherwise we'd have to pass in the current bean instance as well. Defining the semantics for such a public method outside of a concrete sort attempt is not obvious.

What's the use case in Boot to independently introspect the order value?

jhoeller avatar Apr 03 '25 10:04 jhoeller

Thanks for taking a look, @jhoeller.

In org.springframework.boot.web.servlet.ServletContextInitializerBeans, we're essentially finding all beans of type Servlet and Filter (see addAdaptableBeans) and we're creating ServletRegistrationBean and FilterRegistrationBean beans for them. Those RegistrationBean beans should have the same order as the (Servlet and Filter) bean for which they have been created.

Also, it would just work against singletons, otherwise we'd have to pass in the current bean instance as well.

This won't be a problem in this case, as we have both the bean name and the instance.

mhalbritter avatar Apr 03 '25 12:04 mhalbritter

Ah, so you are trying to carry the order over from a target bean to the current bean, locally exposing it through your own Ordered.getOrder() implementation? For certain kinds of components, we could probably expect those target beans to implement Ordered themselves for such an arrangement. However, for freely definable target beans, it's indeed a problem of taking all order sources into account for your Ordered.getOrder() implementation at the front then.

jhoeller avatar Apr 03 '25 13:04 jhoeller

Ah, so you are trying to carry the order over from a target bean to the current bean, locally exposing it through your own Ordered.getOrder() implementation?

Yes, correct.

mhalbritter avatar Apr 03 '25 14:04 mhalbritter