Reputation: 193
There are 3 classes U
, V
, W
implements interface A
and annotated by @Order
annotation of Spring with different order value.
I'm now getting the highest order bean by injecting List<A>
then searching for the first element in List<A>
.
Is there a more direct way to get the highest priority bean without inject whole collection of A
?
Upvotes: 2
Views: 937
Reputation: 21
Consider javax.annotation.Priority. It seems it may help in your case.
@Service
@Priority(Ordered.HIGHEST_PRECEDENCE + 1)
class U implements A {}
@Service
@Priority(Ordered.HIGHEST_PRECEDENCE + 2)
class V implements A {}
@Service
@Priority(Ordered.HIGHEST_PRECEDENCE + 3)
class W implements A {}
interface A {}
@Service
public class Client {
@Autowired
private A a;
@PostConstruct
public void init() {
System.out.println("--------------------------" + a.getClass().getSimpleName());
}
}
'Client.a' will have instance of 'U' assigned.
/**
* Determine the autowire candidate in the given set of beans.
* <p>Looks for {@code @Primary} and {@code @Priority} (in that order).
* @param candidates a Map of candidate names and candidate instances
* that match the required type, as returned by {@link #findAutowireCandidates}
* @param descriptor the target dependency to match against
* @return the name of the autowire candidate, or {@code null} if none found
*/
protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
...
String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
...
}
/**
* Determine the candidate with the highest priority in the given set of beans.
* <p>Based on {@code @javax.annotation.Priority}. As defined by the related
* {@link org.springframework.core.Ordered} interface, the lowest value has
* the highest priority.
* @param candidates a Map of candidate names and candidate instances
* (or candidate classes if not created yet) that match the required type
* @param requiredType the target dependency type to match against
* @return the name of the candidate with the highest priority,
* or {@code null} if none found
* @see #getPriority(Object)
*/
protected String determineHighestPriorityCandidate(Map<String, Object> candidates, Class<?> requiredType) {
String highestPriorityBeanName = null;
Integer highestPriority = null;
for (Map.Entry<String, Object> entry : candidates.entrySet()) {
String candidateBeanName = entry.getKey();
Object beanInstance = entry.getValue();
Integer candidatePriority = getPriority(beanInstance);
if (candidatePriority != null) {
if (highestPriorityBeanName != null) {
if (candidatePriority.equals(highestPriority)) {
throw new NoUniqueBeanDefinitionException(requiredType, candidates.size(),
"Multiple beans found with the same priority ('" + highestPriority +
"') among candidates: " + candidates.keySet());
}
else if (candidatePriority < highestPriority) {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
else {
highestPriorityBeanName = candidateBeanName;
highestPriority = candidatePriority;
}
}
}
return highestPriorityBeanName;
}
Upvotes: 2
Reputation: 53462
As far as I know there isn't any way in spring to directly get only the highest-ordered bean. Your options thus are
@HighestOrdered
, and code your own bean autowiring postprocessor to get only the highest ordered one (example of a custom postprocessor here)Some other options are
But neither of those are exactly the same what you're asking, and have some downsides.
If you strictly want to do what you're asking in the question, I'd just do what you're already doing and iterate them, picking the highest-ordered.
Upvotes: 0