Spring @Order注解使用詳解
前言
很長(zhǎng)一段時(shí)間沒有寫博客了,今天一時(shí)心血來潮,突然寫出這篇文章就很突兀。但是看到網(wǎng)上關(guān)于Spring的@Order注解的不是特別準(zhǔn)確的結(jié)論,想著還是表達(dá)一下看法,當(dāng)然也是通過寫文章來讓自己的思路更清晰一點(diǎn),如果有不是很贊同的部分,希望可以一起討論。
首先先說結(jié)論:Spring的@Order注解(或者實(shí)現(xiàn)Ordered接口、或者實(shí)現(xiàn)PriorityOrdered接口),不決定Bean的實(shí)例化順序和執(zhí)行順序,更不會(huì)影響Spring的Bean的掃描順序;它影響著Spring將掃描的多個(gè)Bean放入數(shù)組、集合(Map)時(shí)的排序。
下面我只驗(yàn)證@Order注解,至于實(shí)現(xiàn)接口的方式有興趣的可以試一下。
例子一
@Slf4j(topic = "e")
@Order(1)
@Component
public class OrderTestService1 {
public OrderTestService1(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(2)
@Component
public class OrderTestService2 {
public OrderTestService2(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(3)
@Component
public class OrderTestService3 {
public OrderTestService3(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
打印順序如下:
OrderTestService1.java 行數(shù)=13 10:56:20.756 [main] DEBUG e - order-1
OrderTestService2.java 行數(shù)=13 10:56:20.760 [main] DEBUG e - order-2
OrderTestService3.java 行數(shù)=13 10:56:20.761 [main] DEBUG e - order-3
例子二
改變OrderTestService三個(gè)類的注解序值
@Slf4j(topic = "e")
@Order(3)
@Component
public class OrderTestService1 {
public OrderTestService1(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(2)
@Component
public class OrderTestService2 {
public OrderTestService2(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(1)
@Component
public class OrderTestService3 {
public OrderTestService3(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}結(jié)果:當(dāng)改變OrderTestService接口的三個(gè)類注解序值時(shí),類的實(shí)例化順序根本沒有變化,即@Order注解不決定Bean的實(shí)例化順序。
例子三
@Slf4j(topic = "e")
public class E {
public void orderList(){
int orderValue = 0;
if(this.getClass().isAnnotationPresent(Order.class)){
Order order = this.getClass().getAnnotation(Order.class);
orderValue = order.value();
}
log.debug("List Order postProcessBeanFactory {} order={}",this.getClass().getSimpleName(),orderValue);
}
}
@Slf4j(topic = "e")
@Order(3)
@Component
public class OrderTestService1 extends E{
public OrderTestService1(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(2)
@Component
public class OrderTestService2 extends E{
public OrderTestService2(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Slf4j(topic = "e")
@Order(1)
@Component
public class OrderTestService3 extends E{
public OrderTestService3(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
}
@Component
public class OrderTestService {
List<E> beanFactoryPostProcessor;
public List<E> getBeanFactoryPostProcessor() {
return beanFactoryPostProcessor;
}
@Autowired
public void setBeanFactoryPostProcessor(List<E> beanFactoryPostProcessor) {
this.beanFactoryPostProcessor = beanFactoryPostProcessor;
}
}打印順序如下:
E.java 行數(shù)=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService3 order=1
E.java 行數(shù)=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService2 order=2
E.java 行數(shù)=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService1 order=3
結(jié)論:當(dāng)通過注入類型為集合或者數(shù)組(可以自行認(rèn)證)時(shí),@Order的注解值影響注入的順序,而這并不代表著說@Order注解影響著Bean的執(zhí)行順序,接著往下看。
實(shí)例論證
不影響B(tài)ean的執(zhí)行順序
然上面的三個(gè)類全都實(shí)現(xiàn)BeanFactoryPostProcessor,然后觀察postProcessBeanFactory方法的執(zhí)行順序,如下:
@Slf4j(topic = "e")
@Order(3)
@Component
public class OrderTestService1 extends E implements BeanFactoryPostProcessor {
public OrderTestService1(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
int orderValue = 0;
if(this.getClass().isAnnotationPresent(Order.class)){
Order order = this.getClass().getAnnotation(Order.class);
orderValue = order.value();
}
log.debug("execute postProcessBeanFactory a order={}",orderValue);
}
}
@Slf4j(topic = "e")
@Order(2)
@Component
public class OrderTestService2 extends E implements BeanFactoryPostProcessor {
public OrderTestService2(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
int orderValue = 0;
if(this.getClass().isAnnotationPresent(Order.class)){
Order order = this.getClass().getAnnotation(Order.class);
orderValue = order.value();
}
log.debug("execute postProcessBeanFactory a order={}",orderValue);
}
}
@Slf4j(topic = "e")
@Order(1)
@Component
public class OrderTestService3 extends E implements BeanFactoryPostProcessor {
public OrderTestService3(){
log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
int orderValue = 0;
if(this.getClass().isAnnotationPresent(Order.class)){
Order order = this.getClass().getAnnotation(Order.class);
orderValue = order.value();
}
log.debug("execute postProcessBeanFactory a order={}",orderValue);
}
}結(jié)論:通過上面的打印結(jié)果,Spring的@Order注解并不影響B(tài)ean的執(zhí)行順序。
接下來主要分析為什么@Order注解在注入類型為集合時(shí)可以影響其順序。
源碼分析
源碼位置:org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency方法中這一段
@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
try {
Object shortcut = descriptor.resolveShortcut(this);
if (shortcut != null) {
return shortcut;
}
// 獲取依賴的類型
Class<?> type = descriptor.getDependencyType();
Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
if (value != null) {
if (value instanceof String) {
String strVal = resolveEmbeddedValue((String) value);
BeanDefinition bd = (beanName != null && containsBean(beanName) ?
getMergedBeanDefinition(beanName) : null);
value = evaluateBeanDefinitionString(strVal, bd);
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
try {
return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
}
catch (UnsupportedOperationException ex) {
// A custom TypeConverter which does not support TypeDescriptor resolution...
return (descriptor.getField() != null ?
converter.convertIfNecessary(value, type, descriptor.getField()) :
converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
}
}
// resolveMultipleBeans方法是解析當(dāng)前依賴項(xiàng)是否支持多個(gè)bean注入 比如list
// 如果是能支持多個(gè)注入則在該方法內(nèi)部就完成了bean的查找,否則下面完成查找
Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
if (multipleBeans != null) {
return multipleBeans;
}
// 完成查找的功能,有可能會(huì)查找出來多個(gè)結(jié)果
// 需要注意的是這里的多個(gè)結(jié)果和上面的支持的多個(gè)注入不是同一回事
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (matchingBeans.isEmpty()) {
// 如果沒有找到而且你又在依賴上面加上了必須的條件,則會(huì)出異常
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
// 如果沒有加必須條件則返回null,意思就是不注入任何對(duì)象
return null;
}
String autowiredBeanName;
Object instanceCandidate;
// 假設(shè)找出來多個(gè)
if (matchingBeans.size() > 1) {
// 通過descriptor 也就是依賴描述器來推斷出來需要注入的這個(gè)對(duì)象的名字
// 注意這里不是當(dāng)前注入對(duì)象的名字而是需要注入的對(duì)象的名字
// 假設(shè)A依賴B,這里推斷的B這個(gè)對(duì)象應(yīng)該叫什么名字
autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
// 假設(shè)推斷出來為null
// 什么情況下為null?就是你提供的名字和任何找出來的對(duì)象的名字匹配不上
if (autowiredBeanName == null) {
if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
}
else {
// In case of an optional Collection/Map, silently ignore a non-unique case:
// possibly it was meant to be an empty collection of multiple regular beans
// (before 4.3 in particular when we didn't even look for collection beans).
return null;
}
}
// 獲取類 通過名字
instanceCandidate = matchingBeans.get(autowiredBeanName);
}
else {
// We have exactly one match.
Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
autowiredBeanName = entry.getKey();
instanceCandidate = entry.getValue();
}
if (autowiredBeanNames != null) {
autowiredBeanNames.add(autowiredBeanName);
}
if (instanceCandidate instanceof Class) {
instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
}
Object result = instanceCandidate;
if (result instanceof NullBean) {
if (isRequired(descriptor)) {
raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
}
result = null;
}
if (!ClassUtils.isAssignableValue(type, result)) {
throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
}
return result;
}
finally {
ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
}
}主要看這一句:Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
@Nullable
private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
Class<?> type = descriptor.getDependencyType();
if (descriptor instanceof StreamDependencyDescriptor) {
// findAutowireCandidates 根據(jù)類型查詢
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
Stream<Object> stream = matchingBeans.keySet().stream()
.map(name -> descriptor.resolveCandidate(name, type, this))
.filter(bean -> !(bean instanceof NullBean));
if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
stream = stream.sorted(adaptOrderComparator(matchingBeans));
}
return stream;
}
else if (type.isArray()) {
Class<?> componentType = type.getComponentType();
ResolvableType resolvableType = descriptor.getResolvableType();
Class<?> resolvedArrayType = resolvableType.resolve(type);
if (resolvedArrayType != type) {
componentType = resolvableType.getComponentType().resolve();
}
if (componentType == null) {
return null;
}
// findAutowireCandidates 根據(jù)類型查詢
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
if (result instanceof Object[]) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
Arrays.sort((Object[]) result, comparator);
}
}
return result;
}
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
// findAutowireCandidates 根據(jù)類型查詢
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
if (((List<?>) result).size() > 1) {
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
}
else if (Map.class == type) {
ResolvableType mapType = descriptor.getResolvableType().asMap();
Class<?> keyType = mapType.resolveGeneric(0);
if (String.class != keyType) {
return null;
}
Class<?> valueType = mapType.resolveGeneric(1);
if (valueType == null) {
return null;
}
// findAutowireCandidates 根據(jù)類型查詢
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
return matchingBeans;
}
else {
return null;
}
}主要看這一段:
else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
if (elementType == null) {
return null;
}
// findAutowireCandidates 根據(jù)類型查詢
Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
new MultiElementDescriptor(descriptor));
if (matchingBeans.isEmpty()) {
return null;
}
if (autowiredBeanNames != null) {
autowiredBeanNames.addAll(matchingBeans.keySet());
}
TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
Object result = converter.convertIfNecessary(matchingBeans.values(), type);
if (result instanceof List) {
if (((List<?>) result).size() > 1) {
// 調(diào)用比較器
Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
if (comparator != null) {
((List<?>) result).sort(comparator);
}
}
}
return result;
} @Nullable
private Comparator<Object> adaptDependencyComparator(Map<String, ?> matchingBeans) {
// 獲取比較器
Comparator<Object> comparator = getDependencyComparator();
if (comparator instanceof OrderComparator) {
return ((OrderComparator) comparator).withSourceProvider(
createFactoryAwareOrderSourceProvider(matchingBeans));
}
else {
return comparator;
}
}
public Comparator<Object> withSourceProvider(OrderSourceProvider sourceProvider) {
return (o1, o2) -> doCompare(o1, o2, sourceProvider);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
// 是否實(shí)現(xiàn)了PriorityOrdered接口
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}接下來比較重要,上面注釋了是否實(shí)現(xiàn)了PriorityOrdered接口,如果沒有則調(diào)用getOrder方法,getOrder方法判斷是否實(shí)現(xiàn)了Order接口,如果沒有獲取@Order注解值。
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
// 拿到實(shí)現(xiàn)了Order接口的類
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
for (Object source : ObjectUtils.toObjectArray(orderSource)) {
order = findOrder(source);
if (order != null) {
break;
}
}
}
else {
order = findOrder(orderSource);
}
}
}
return (order != null ? order : getOrder(obj));
}
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}
@Override
@Nullable
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
return findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
if (order == null && obj instanceof DecoratingProxy) {
return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
}
return order;
}總結(jié)下來就是:當(dāng)我們通過構(gòu)造函數(shù)或者set方法注入進(jìn)某個(gè)List<類>時(shí),Spring的DefaultListableBeanFactory類會(huì)在注入時(shí)獲取AnnotationAwareOrderComparator比較器幫助我們對(duì)類進(jìn)行排序,AnnotationAwareOrderComparator是OrderComparator的子類,而OrderComparator實(shí)現(xiàn)了比較器Comparator接口。排序的策略會(huì)先判斷是否實(shí)現(xiàn)PriorityOrdered接口,如果沒有接著會(huì)判斷是否實(shí)現(xiàn)Order接口,此時(shí)也沒有就會(huì)根據(jù)注解值進(jìn)行比較。
到此這篇關(guān)于Spring @Order注解使用詳解的文章就介紹到這了,更多相關(guān)Spring @Order 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java 中如何使用 JavaFx 庫標(biāo)注文本顏色
這篇文章主要介紹了在 Java 中用 JavaFx 庫標(biāo)注文本顏色,在本文中,我們將了解如何更改標(biāo)簽的文本顏色,并且我們還將看到一個(gè)必要的示例和適當(dāng)?shù)慕忉?,以便更容易理解該主題,需要的朋友可以參考下2023-05-05
Mybatis-Plus中Mapper的接口文件與xml文件相關(guān)的坑記錄
這篇文章主要介紹了Mybatis-Plus中Mapper的接口文件與xml文件相關(guān)的坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
MyBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)
下面小編就為大家?guī)硪黄狹yBatis_Generator插件的安裝以及簡(jiǎn)單使用方法(圖解)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-05-05
eclipse maven maven-archetype-webapp 創(chuàng)建失敗問題解決
這篇文章主要介紹了eclipse maven maven-archetype-webapp 創(chuàng)建失敗問題解決的相關(guān)資料,需要的朋友可以參考下2016-12-12
rabbitmq消息ACK確認(rèn)機(jī)制及發(fā)送失敗處理方式
這篇文章主要介紹了rabbitmq消息ACK確認(rèn)機(jī)制及發(fā)送失敗處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
最長(zhǎng)重復(fù)子數(shù)組 findLength示例詳解
今天給大家分享一道比較常問的算法面試題,最長(zhǎng)重復(fù)子數(shù)組 findLength,文中給大家分享解題思路,結(jié)合示例代碼介紹的非常詳細(xì),需要的朋友參考下吧2023-08-08

