欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring @Order注解使用詳解

 更新時間:2022年08月15日 15:35:39   作者:l昨日青天  
注解@Order或者接口Ordered的作用是定義Spring IOC容器中Bean的執(zhí)行順序的優(yōu)先級,而不是定義Bean的加載順序,Bean的加載順序不受@Order或Ordered接口的影響

前言

很長一段時間沒有寫博客了,今天一時心血來潮,突然寫出這篇文章就很突兀。但是看到網上關于Spring的@Order注解的不是特別準確的結論,想著還是表達一下看法,當然也是通過寫文章來讓自己的思路更清晰一點,如果有不是很贊同的部分,希望可以一起討論。

首先先說結論:Spring的@Order注解(或者實現Ordered接口、或者實現PriorityOrdered接口),不決定Bean的實例化順序和執(zhí)行順序,更不會影響Spring的Bean的掃描順序;它影響著Spring將掃描的多個Bean放入數組、集合(Map)時的排序。

下面我只驗證@Order注解,至于實現接口的方式有興趣的可以試一下。

例子一

@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 行數=13 10:56:20.756 [main] DEBUG e - order-1
OrderTestService2.java 行數=13 10:56:20.760 [main] DEBUG e - order-2
OrderTestService3.java 行數=13 10:56:20.761 [main] DEBUG e - order-3

例子二

改變OrderTestService三個類的注解序值

@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());
	}
}

結果:當改變OrderTestService接口的三個類注解序值時,類的實例化順序根本沒有變化,即@Order注解不決定Bean的實例化順序。

例子三

@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 行數=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService3 order=1
E.java 行數=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService2 order=2
E.java 行數=15 11:01:47.756 [main] DEBUG e - List Order postProcessBeanFactory OrderTestService1 order=3

結論:當通過注入類型為集合或者數組(可以自行認證)時,@Order的注解值影響注入的順序,而這并不代表著說@Order注解影響著Bean的執(zhí)行順序,接著往下看。

實例論證

不影響B(tài)ean的執(zhí)行順序

然上面的三個類全都實現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);
	}
}

結論:通過上面的打印結果,Spring的@Order注解并不影響B(tài)ean的執(zhí)行順序。

接下來主要分析為什么@Order注解在注入類型為集合時可以影響其順序。

源碼分析

源碼位置: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方法是解析當前依賴項是否支持多個bean注入 比如list
			// 如果是能支持多個注入則在該方法內部就完成了bean的查找,否則下面完成查找
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			// 完成查找的功能,有可能會查找出來多個結果
			// 需要注意的是這里的多個結果和上面的支持的多個注入不是同一回事
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// 如果沒有找到而且你又在依賴上面加上了必須的條件,則會出異常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				// 如果沒有加必須條件則返回null,意思就是不注入任何對象
				return null;
			}
			String autowiredBeanName;
			Object instanceCandidate;
			// 假設找出來多個
			if (matchingBeans.size() > 1) {
				// 通過descriptor 也就是依賴描述器來推斷出來需要注入的這個對象的名字
				// 注意這里不是當前注入對象的名字而是需要注入的對象的名字
				// 假設A依賴B,這里推斷的B這個對象應該叫什么名字
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				// 假設推斷出來為null
				// 什么情況下為null?就是你提供的名字和任何找出來的對象的名字匹配不上
				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 根據類型查詢
			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 根據類型查詢
			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 根據類型查詢
			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 根據類型查詢
			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 根據類型查詢
			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;
		}
	@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) {
		// 是否實現了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);
	}

接下來比較重要,上面注釋了是否實現了PriorityOrdered接口,如果沒有則調用getOrder方法,getOrder方法判斷是否實現了Order接口,如果沒有獲取@Order注解值。

	private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
		Integer order = null;
		if (obj != null && sourceProvider != null) {
			// 拿到實現了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;
	}

總結下來就是:當我們通過構造函數或者set方法注入進某個List<類>時,Spring的DefaultListableBeanFactory類會在注入時獲取AnnotationAwareOrderComparator比較器幫助我們對類進行排序,AnnotationAwareOrderComparator是OrderComparator的子類,而OrderComparator實現了比較器Comparator接口。排序的策略會先判斷是否實現PriorityOrdered接口,如果沒有接著會判斷是否實現Order接口,此時也沒有就會根據注解值進行比較。

到此這篇關于Spring @Order注解使用詳解的文章就介紹到這了,更多相關Spring @Order 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Springboot使用@Cacheable注解實現數據緩存

    Springboot使用@Cacheable注解實現數據緩存

    本文介紹如何在Springboot中通過@Cacheable注解實現數據緩存,在每次調用添加了@Cacheable注解的方法時,Spring 會檢查指定參數的指定目標方法是否已經被調用過,文中有詳細的代碼示例,需要的朋友可以參考下
    2023-10-10
  • 深入java事件注冊的應用分析

    深入java事件注冊的應用分析

    本篇文章是對java事件注冊進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • Java?SE使用for?each循環(huán)遍歷數組的方法代碼

    Java?SE使用for?each循環(huán)遍歷數組的方法代碼

    在Java?SE開發(fā)中,數組是最常見的數據結構之一,Java提供了多種遍歷數組的方式,其中for循環(huán)是最常用的方式之一,本文將介紹如何使用for?each循環(huán)遍歷數組,接下來,我們將通過一個簡單的代碼示例來展示如何使用for?each循環(huán)遍歷數組,需要的朋友可以參考下
    2023-11-11
  • Java中@Async異步失效的9種場景

    Java中@Async異步失效的9種場景

    最近在項目某個方法使用@Async注解,但是該方法還是同步執(zhí)行了,異步不起作用,到底是什么原因呢?接下來本文給大家介紹了Java?@Async異步失效的9種場景,需要的朋友可以參考下
    2024-05-05
  • HttpServletResponse亂碼問題_動力節(jié)點Java學院整理

    HttpServletResponse亂碼問題_動力節(jié)點Java學院整理

    這篇文章主要介紹了HttpServletResponse亂碼問題,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 關于maven pom文件配置加載lib下的jar包

    關于maven pom文件配置加載lib下的jar包

    在項目中引用放置在lib文件夾中的第三方jar包需要通過POM文件進行特定配置,雖然將依賴放置在公司的Maven私服是更好的做法,但如果遇到部署問題,可以利用maven-jar-plugin進行配置,Spring Boot項目可以通過特定設置來實現
    2024-09-09
  • MyBatis流式查詢的使用詳解

    MyBatis流式查詢的使用詳解

    流式查詢指的是查詢成功后不是返回一個集合而是返回一個迭代器,應用每次從迭代器取一條查詢結果。流式查詢的好處是能夠降低內存使用
    2022-08-08
  • SpringBoot通過tractId操作日志鏈路跟蹤

    SpringBoot通過tractId操作日志鏈路跟蹤

    這篇文章給大家介紹SpringBoot通過tractId操作日志鏈路跟蹤,通過tractId,即可完成對從一個請求進入系統(tǒng)到請求結束的日志追蹤,本文給大家介紹的非常詳細,需要的朋友參考下吧
    2023-10-10
  • 在SpringBoot中實現多種方式登錄(通過用戶名、手機號、郵箱等)的詳細指南

    在SpringBoot中實現多種方式登錄(通過用戶名、手機號、郵箱等)的詳細指南

    今天,我們將跳進 Spring Boot 的世界,探索如何通過 用戶名、手機號、郵箱 等多種方式實現登錄,而我們要做的就是為他們提供這些選擇,確保他們都能毫無阻礙地進入我們的系統(tǒng),感興趣的小伙伴跟著小編一起來看看吧
    2024-11-11
  • 在spring中實例化bean無效的問題

    在spring中實例化bean無效的問題

    這篇文章主要介紹了在spring中實例化bean無效的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評論