Spring @Order注解使用詳解
前言
很長(zhǎng)一段時(shí)間沒(méi)有寫(xiě)博客了,今天一時(shí)心血來(lái)潮,突然寫(xiě)出這篇文章就很突兀。但是看到網(wǎng)上關(guān)于Spring的@Order注解的不是特別準(zhǔn)確的結(jié)論,想著還是表達(dá)一下看法,當(dāng)然也是通過(guò)寫(xiě)文章來(lái)讓自己的思路更清晰一點(diǎn),如果有不是很贊同的部分,希望可以一起討論。
首先先說(shuō)結(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è)類(lèi)的注解序值
@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è)類(lèi)注解序值時(shí),類(lèi)的實(shí)例化順序根本沒(méi)有變化,即@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)通過(guò)注入類(lèi)型為集合或者數(shù)組(可以自行認(rèn)證)時(shí),@Order的注解值影響注入的順序,而這并不代表著說(shuō)@Order注解影響著B(niǎo)ean的執(zhí)行順序,接著往下看。
實(shí)例論證
不影響B(tài)ean的執(zhí)行順序
然上面的三個(gè)類(lèi)全都實(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é)論:通過(guò)上面的打印結(jié)果,Spring的@Order注解并不影響B(tài)ean的執(zhí)行順序。
接下來(lái)主要分析為什么@Order注解在注入類(lèi)型為集合時(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; } // 獲取依賴(lài)的類(lèi)型 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)前依賴(lài)項(xiàng)是否支持多個(gè)bean注入 比如list // 如果是能支持多個(gè)注入則在該方法內(nèi)部就完成了bean的查找,否則下面完成查找 Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter); if (multipleBeans != null) { return multipleBeans; } // 完成查找的功能,有可能會(huì)查找出來(lái)多個(gè)結(jié)果 // 需要注意的是這里的多個(gè)結(jié)果和上面的支持的多個(gè)注入不是同一回事 Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor); if (matchingBeans.isEmpty()) { // 如果沒(méi)有找到而且你又在依賴(lài)上面加上了必須的條件,則會(huì)出異常 if (isRequired(descriptor)) { raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor); } // 如果沒(méi)有加必須條件則返回null,意思就是不注入任何對(duì)象 return null; } String autowiredBeanName; Object instanceCandidate; // 假設(shè)找出來(lái)多個(gè) if (matchingBeans.size() > 1) { // 通過(guò)descriptor 也就是依賴(lài)描述器來(lái)推斷出來(lái)需要注入的這個(gè)對(duì)象的名字 // 注意這里不是當(dāng)前注入對(duì)象的名字而是需要注入的對(duì)象的名字 // 假設(shè)A依賴(lài)B,這里推斷的B這個(gè)對(duì)象應(yīng)該叫什么名字 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor); // 假設(shè)推斷出來(lái)為null // 什么情況下為null?就是你提供的名字和任何找出來(lái)的對(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; } } // 獲取類(lèi) 通過(guò)名字 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ù)類(lèi)型查詢 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ù)類(lèi)型查詢 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ù)類(lèi)型查詢 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ù)類(lèi)型查詢 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ù)類(lèi)型查詢 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); }
接下來(lái)比較重要,上面注釋了是否實(shí)現(xiàn)了PriorityOrdered接口,如果沒(méi)有則調(diào)用getOrder方法,getOrder方法判斷是否實(shí)現(xiàn)了Order接口,如果沒(méi)有獲取@Order注解值。
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) { Integer order = null; if (obj != null && sourceProvider != null) { // 拿到實(shí)現(xiàn)了Order接口的類(lèi) 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é)下來(lái)就是:當(dāng)我們通過(guò)構(gòu)造函數(shù)或者set方法注入進(jìn)某個(gè)List<類(lèi)>時(shí),Spring的DefaultListableBeanFactory類(lèi)會(huì)在注入時(shí)獲取AnnotationAwareOrderComparator比較器幫助我們對(duì)類(lèi)進(jìn)行排序,AnnotationAwareOrderComparator是OrderComparator的子類(lèi),而OrderComparator實(shí)現(xiàn)了比較器Comparator接口。排序的策略會(huì)先判斷是否實(shí)現(xiàn)PriorityOrdered接口,如果沒(méi)有接著會(huì)判斷是否實(shí)現(xiàn)Order接口,此時(shí)也沒(méi)有就會(huì)根據(jù)注解值進(jìn)行比較。
到此這篇關(guān)于Spring @Order注解使用詳解的文章就介紹到這了,更多相關(guān)Spring @Order 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot使用@Cacheable注解實(shí)現(xiàn)數(shù)據(jù)緩存
本文介紹如何在Springboot中通過(guò)@Cacheable注解實(shí)現(xiàn)數(shù)據(jù)緩存,在每次調(diào)用添加了@Cacheable注解的方法時(shí),Spring 會(huì)檢查指定參數(shù)的指定目標(biāo)方法是否已經(jīng)被調(diào)用過(guò),文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10Java?SE使用for?each循環(huán)遍歷數(shù)組的方法代碼
在Java?SE開(kāi)發(fā)中,數(shù)組是最常見(jiàn)的數(shù)據(jù)結(jié)構(gòu)之一,Java提供了多種遍歷數(shù)組的方式,其中for循環(huán)是最常用的方式之一,本文將介紹如何使用for?each循環(huán)遍歷數(shù)組,接下來(lái),我們將通過(guò)一個(gè)簡(jiǎn)單的代碼示例來(lái)展示如何使用for?each循環(huán)遍歷數(shù)組,需要的朋友可以參考下2023-11-11HttpServletResponse亂碼問(wèn)題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了HttpServletResponse亂碼問(wèn)題,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07關(guān)于maven pom文件配置加載lib下的jar包
在項(xiàng)目中引用放置在lib文件夾中的第三方j(luò)ar包需要通過(guò)POM文件進(jìn)行特定配置,雖然將依賴(lài)放置在公司的Maven私服是更好的做法,但如果遇到部署問(wèn)題,可以利用maven-jar-plugin進(jìn)行配置,Spring Boot項(xiàng)目可以通過(guò)特定設(shè)置來(lái)實(shí)現(xiàn)2024-09-09SpringBoot通過(guò)tractId操作日志鏈路跟蹤
這篇文章給大家介紹SpringBoot通過(guò)tractId操作日志鏈路跟蹤,通過(guò)tractId,即可完成對(duì)從一個(gè)請(qǐng)求進(jìn)入系統(tǒng)到請(qǐng)求結(jié)束的日志追蹤,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10在SpringBoot中實(shí)現(xiàn)多種方式登錄(通過(guò)用戶名、手機(jī)號(hào)、郵箱等)的詳細(xì)指南
今天,我們將跳進(jìn) Spring Boot 的世界,探索如何通過(guò) 用戶名、手機(jī)號(hào)、郵箱 等多種方式實(shí)現(xiàn)登錄,而我們要做的就是為他們提供這些選擇,確保他們都能毫無(wú)阻礙地進(jìn)入我們的系統(tǒng),感興趣的小伙伴跟著小編一起來(lái)看看吧2024-11-11在spring中實(shí)例化bean無(wú)效的問(wèn)題
這篇文章主要介紹了在spring中實(shí)例化bean無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02