经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Spring » 查看文章
Spring @Order注解使用详解
来源:jb51  时间:2022/8/15 16:59:30  对本文有异议

前言

很长一段时间没有写博客了,今天一时心血来潮,突然写出这篇文章就很突兀。但是看到网上关于Spring的@Order注解的不是特别准确的结论,想着还是表达一下看法,当然也是通过写文章来让自己的思路更清晰一点,如果有不是很赞同的部分,希望可以一起讨论。

首先先说结论:Spring的@Order注解(或者实现Ordered接口、或者实现PriorityOrdered接口),不决定Bean的实例化顺序和执行顺序,更不会影响Spring的Bean的扫描顺序;它影响着Spring将扫描的多个Bean放入数组、集合(Map)时的排序。

下面我只验证@Order注解,至于实现接口的方式有兴趣的可以试一下。

例子一

  1. @Slf4j(topic = "e")
  2. @Order(1)
  3. @Component
  4. public class OrderTestService1 {
  5. public OrderTestService1(){
  6. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  7. }
  8. }
  9. @Slf4j(topic = "e")
  10. @Order(2)
  11. @Component
  12. public class OrderTestService2 {
  13. public OrderTestService2(){
  14. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  15. }
  16. }
  17. @Slf4j(topic = "e")
  18. @Order(3)
  19. @Component
  20. public class OrderTestService3 {
  21. public OrderTestService3(){
  22. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  23. }
  24. }

打印顺序如下:
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三个类的注解序值

  1. @Slf4j(topic = "e")
  2. @Order(3)
  3. @Component
  4. public class OrderTestService1 {
  5. public OrderTestService1(){
  6. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  7. }
  8.  
  9. }
  10. @Slf4j(topic = "e")
  11. @Order(2)
  12. @Component
  13. public class OrderTestService2 {
  14. public OrderTestService2(){
  15. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  16. }
  17. }
  18. @Slf4j(topic = "e")
  19. @Order(1)
  20. @Component
  21. public class OrderTestService3 {
  22. public OrderTestService3(){
  23. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  24. }
  25. }

结果:当改变OrderTestService接口的三个类注解序值时,类的实例化顺序根本没有变化,即@Order注解不决定Bean的实例化顺序。

例子三

  1. @Slf4j(topic = "e")
  2. public class E {
  3. public void orderList(){
  4. int orderValue = 0;
  5. if(this.getClass().isAnnotationPresent(Order.class)){
  6. Order order = this.getClass().getAnnotation(Order.class);
  7. orderValue = order.value();
  8. }
  9. log.debug("List Order postProcessBeanFactory {} order={}",this.getClass().getSimpleName(),orderValue);
  10. }
  11. }
  12. @Slf4j(topic = "e")
  13. @Order(3)
  14. @Component
  15. public class OrderTestService1 extends E{
  16. public OrderTestService1(){
  17. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  18. }
  19. }
  20. @Slf4j(topic = "e")
  21. @Order(2)
  22. @Component
  23. public class OrderTestService2 extends E{
  24. public OrderTestService2(){
  25. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  26. }
  27. }
  28. @Slf4j(topic = "e")
  29. @Order(1)
  30. @Component
  31. public class OrderTestService3 extends E{
  32. public OrderTestService3(){
  33. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  34. }
  35. }
  36. @Component
  37. public class OrderTestService {
  38. List<E> beanFactoryPostProcessor;
  39. public List<E> getBeanFactoryPostProcessor() {
  40. return beanFactoryPostProcessor;
  41. }
  42. @Autowired
  43. public void setBeanFactoryPostProcessor(List<E> beanFactoryPostProcessor) {
  44. this.beanFactoryPostProcessor = beanFactoryPostProcessor;
  45. }
  46. }

打印顺序如下:
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的执行顺序,接着往下看。

实例论证

不影响Bean的执行顺序

然上面的三个类全都实现BeanFactoryPostProcessor,然后观察postProcessBeanFactory方法的执行顺序,如下:

  1. @Slf4j(topic = "e")
  2. @Order(3)
  3. @Component
  4. public class OrderTestService1 extends E implements BeanFactoryPostProcessor {
  5. public OrderTestService1(){
  6. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  7. }
  8. @Override
  9. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  10. int orderValue = 0;
  11. if(this.getClass().isAnnotationPresent(Order.class)){
  12. Order order = this.getClass().getAnnotation(Order.class);
  13. orderValue = order.value();
  14. }
  15. log.debug("execute postProcessBeanFactory a order={}",orderValue);
  16. }
  17. }
  18. @Slf4j(topic = "e")
  19. @Order(2)
  20. @Component
  21. public class OrderTestService2 extends E implements BeanFactoryPostProcessor {
  22. public OrderTestService2(){
  23. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  24. }
  25. @Override
  26. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  27. int orderValue = 0;
  28. if(this.getClass().isAnnotationPresent(Order.class)){
  29. Order order = this.getClass().getAnnotation(Order.class);
  30. orderValue = order.value();
  31. }
  32. log.debug("execute postProcessBeanFactory a order={}",orderValue);
  33. }
  34. }
  35. @Slf4j(topic = "e")
  36. @Order(1)
  37. @Component
  38. public class OrderTestService3 extends E implements BeanFactoryPostProcessor {
  39. public OrderTestService3(){
  40. log.debug("order-{}",this.getClass().getAnnotation(Order.class).value());
  41. }
  42. @Override
  43. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
  44. int orderValue = 0;
  45. if(this.getClass().isAnnotationPresent(Order.class)){
  46. Order order = this.getClass().getAnnotation(Order.class);
  47. orderValue = order.value();
  48. }
  49. log.debug("execute postProcessBeanFactory a order={}",orderValue);
  50. }
  51. }

结论:通过上面的打印结果,Spring的@Order注解并不影响Bean的执行顺序。

接下来主要分析为什么@Order注解在注入类型为集合时可以影响其顺序。

源码分析

源码位置:org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency方法中这一段

  1. @Nullable
  2. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
  3. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
  4. InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
  5. try {
  6. Object shortcut = descriptor.resolveShortcut(this);
  7. if (shortcut != null) {
  8. return shortcut;
  9. }
  10. // 获取依赖的类型
  11. Class<?> type = descriptor.getDependencyType();
  12. Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
  13. if (value != null) {
  14. if (value instanceof String) {
  15. String strVal = resolveEmbeddedValue((String) value);
  16. BeanDefinition bd = (beanName != null && containsBean(beanName) ?
  17. getMergedBeanDefinition(beanName) : null);
  18. value = evaluateBeanDefinitionString(strVal, bd);
  19. }
  20. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  21. try {
  22. return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
  23. }
  24. catch (UnsupportedOperationException ex) {
  25. // A custom TypeConverter which does not support TypeDescriptor resolution...
  26. return (descriptor.getField() != null ?
  27. converter.convertIfNecessary(value, type, descriptor.getField()) :
  28. converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
  29. }
  30. }
  31. // resolveMultipleBeans方法是解析当前依赖项是否支持多个bean注入 比如list
  32. // 如果是能支持多个注入则在该方法内部就完成了bean的查找,否则下面完成查找
  33. Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
  34. if (multipleBeans != null) {
  35. return multipleBeans;
  36. }
  37. // 完成查找的功能,有可能会查找出来多个结果
  38. // 需要注意的是这里的多个结果和上面的支持的多个注入不是同一回事
  39. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  40. if (matchingBeans.isEmpty()) {
  41. // 如果没有找到而且你又在依赖上面加上了必须的条件,则会出异常
  42. if (isRequired(descriptor)) {
  43. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  44. }
  45. // 如果没有加必须条件则返回null,意思就是不注入任何对象
  46. return null;
  47. }
  48. String autowiredBeanName;
  49. Object instanceCandidate;
  50. // 假设找出来多个
  51. if (matchingBeans.size() > 1) {
  52. // 通过descriptor 也就是依赖描述器来推断出来需要注入的这个对象的名字
  53. // 注意这里不是当前注入对象的名字而是需要注入的对象的名字
  54. // 假设A依赖B,这里推断的B这个对象应该叫什么名字
  55. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
  56. // 假设推断出来为null
  57. // 什么情况下为null?就是你提供的名字和任何找出来的对象的名字匹配不上
  58. if (autowiredBeanName == null) {
  59. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
  60. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
  61. }
  62. else {
  63. // In case of an optional Collection/Map, silently ignore a non-unique case:
  64. // possibly it was meant to be an empty collection of multiple regular beans
  65. // (before 4.3 in particular when we didn't even look for collection beans).
  66. return null;
  67. }
  68. }
  69. // 获取类 通过名字
  70. instanceCandidate = matchingBeans.get(autowiredBeanName);
  71. }
  72. else {
  73. // We have exactly one match.
  74. Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
  75. autowiredBeanName = entry.getKey();
  76. instanceCandidate = entry.getValue();
  77. }
  78. if (autowiredBeanNames != null) {
  79. autowiredBeanNames.add(autowiredBeanName);
  80. }
  81. if (instanceCandidate instanceof Class) {
  82. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
  83. }
  84. Object result = instanceCandidate;
  85. if (result instanceof NullBean) {
  86. if (isRequired(descriptor)) {
  87. raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
  88. }
  89. result = null;
  90. }
  91. if (!ClassUtils.isAssignableValue(type, result)) {
  92. throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
  93. }
  94. return result;
  95. }
  96. finally {
  97. ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
  98. }
  99. }

主要看这一句:Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

  1. @Nullable
  2. private Object resolveMultipleBeans(DependencyDescriptor descriptor, @Nullable String beanName,
  3. @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) {
  4. Class<?> type = descriptor.getDependencyType();
  5. if (descriptor instanceof StreamDependencyDescriptor) {
  6. // findAutowireCandidates 根据类型查询
  7. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
  8. if (autowiredBeanNames != null) {
  9. autowiredBeanNames.addAll(matchingBeans.keySet());
  10. }
  11. Stream<Object> stream = matchingBeans.keySet().stream()
  12. .map(name -> descriptor.resolveCandidate(name, type, this))
  13. .filter(bean -> !(bean instanceof NullBean));
  14. if (((StreamDependencyDescriptor) descriptor).isOrdered()) {
  15. stream = stream.sorted(adaptOrderComparator(matchingBeans));
  16. }
  17. return stream;
  18. }
  19. else if (type.isArray()) {
  20. Class<?> componentType = type.getComponentType();
  21. ResolvableType resolvableType = descriptor.getResolvableType();
  22. Class<?> resolvedArrayType = resolvableType.resolve(type);
  23. if (resolvedArrayType != type) {
  24. componentType = resolvableType.getComponentType().resolve();
  25. }
  26. if (componentType == null) {
  27. return null;
  28. }
  29. // findAutowireCandidates 根据类型查询
  30. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, componentType,
  31. new MultiElementDescriptor(descriptor));
  32. if (matchingBeans.isEmpty()) {
  33. return null;
  34. }
  35. if (autowiredBeanNames != null) {
  36. autowiredBeanNames.addAll(matchingBeans.keySet());
  37. }
  38. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  39. Object result = converter.convertIfNecessary(matchingBeans.values(), resolvedArrayType);
  40. if (result instanceof Object[]) {
  41. Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
  42. if (comparator != null) {
  43. Arrays.sort((Object[]) result, comparator);
  44. }
  45. }
  46. return result;
  47. }
  48. else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
  49. Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
  50. if (elementType == null) {
  51. return null;
  52. }
  53. // findAutowireCandidates 根据类型查询
  54. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
  55. new MultiElementDescriptor(descriptor));
  56. if (matchingBeans.isEmpty()) {
  57. return null;
  58. }
  59. if (autowiredBeanNames != null) {
  60. autowiredBeanNames.addAll(matchingBeans.keySet());
  61. }
  62. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  63. Object result = converter.convertIfNecessary(matchingBeans.values(), type);
  64. if (result instanceof List) {
  65. if (((List<?>) result).size() > 1) {
  66. Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
  67. if (comparator != null) {
  68. ((List<?>) result).sort(comparator);
  69. }
  70. }
  71. }
  72. return result;
  73. }
  74. else if (Map.class == type) {
  75. ResolvableType mapType = descriptor.getResolvableType().asMap();
  76. Class<?> keyType = mapType.resolveGeneric(0);
  77. if (String.class != keyType) {
  78. return null;
  79. }
  80. Class<?> valueType = mapType.resolveGeneric(1);
  81. if (valueType == null) {
  82. return null;
  83. }
  84. // findAutowireCandidates 根据类型查询
  85. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
  86. new MultiElementDescriptor(descriptor));
  87. if (matchingBeans.isEmpty()) {
  88. return null;
  89. }
  90. if (autowiredBeanNames != null) {
  91. autowiredBeanNames.addAll(matchingBeans.keySet());
  92. }
  93. return matchingBeans;
  94. }
  95. else {
  96. return null;
  97. }
  98. }

主要看这一段:

  1. else if (Collection.class.isAssignableFrom(type) && type.isInterface()) {
  2. Class<?> elementType = descriptor.getResolvableType().asCollection().resolveGeneric();
  3. if (elementType == null) {
  4. return null;
  5. }
  6. // findAutowireCandidates 根据类型查询
  7. Map<String, Object> matchingBeans = findAutowireCandidates(beanName, elementType,
  8. new MultiElementDescriptor(descriptor));
  9. if (matchingBeans.isEmpty()) {
  10. return null;
  11. }
  12. if (autowiredBeanNames != null) {
  13. autowiredBeanNames.addAll(matchingBeans.keySet());
  14. }
  15. TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
  16. Object result = converter.convertIfNecessary(matchingBeans.values(), type);
  17. if (result instanceof List) {
  18. if (((List<?>) result).size() > 1) {
  19. // 调用比较器
  20. Comparator<Object> comparator = adaptDependencyComparator(matchingBeans);
  21. if (comparator != null) {
  22. ((List<?>) result).sort(comparator);
  23. }
  24. }
  25. }
  26. return result;
  27. }
  1. @Nullable
  2. private Comparator<Object> adaptDependencyComparator(Map<String, ?> matchingBeans) {
  3. // 获取比较器
  4. Comparator<Object> comparator = getDependencyComparator();
  5. if (comparator instanceof OrderComparator) {
  6. return ((OrderComparator) comparator).withSourceProvider(
  7. createFactoryAwareOrderSourceProvider(matchingBeans));
  8. }
  9. else {
  10. return comparator;
  11. }
  12. }
  13. public Comparator<Object> withSourceProvider(OrderSourceProvider sourceProvider) {
  14. return (o1, o2) -> doCompare(o1, o2, sourceProvider);
  15. }
  16. private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
  17. // 是否实现了PriorityOrdered接口
  18. boolean p1 = (o1 instanceof PriorityOrdered);
  19. boolean p2 = (o2 instanceof PriorityOrdered);
  20. if (p1 && !p2) {
  21. return -1;
  22. }
  23. else if (p2 && !p1) {
  24. return 1;
  25. }
  26. int i1 = getOrder(o1, sourceProvider);
  27. int i2 = getOrder(o2, sourceProvider);
  28. return Integer.compare(i1, i2);
  29. }

接下来比较重要,上面注释了是否实现了PriorityOrdered接口,如果没有则调用getOrder方法,getOrder方法判断是否实现了Order接口,如果没有获取@Order注解值。

  1. private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
  2. Integer order = null;
  3. if (obj != null && sourceProvider != null) {
  4. // 拿到实现了Order接口的类
  5. Object orderSource = sourceProvider.getOrderSource(obj);
  6. if (orderSource != null) {
  7. if (orderSource.getClass().isArray()) {
  8. for (Object source : ObjectUtils.toObjectArray(orderSource)) {
  9. order = findOrder(source);
  10. if (order != null) {
  11. break;
  12. }
  13. }
  14. }
  15. else {
  16. order = findOrder(orderSource);
  17. }
  18. }
  19. }
  20. return (order != null ? order : getOrder(obj));
  21. }
  22. protected int getOrder(@Nullable Object obj) {
  23. if (obj != null) {
  24. Integer order = findOrder(obj);
  25. if (order != null) {
  26. return order;
  27. }
  28. }
  29. return Ordered.LOWEST_PRECEDENCE;
  30. }
  31. @Override
  32. @Nullable
  33. protected Integer findOrder(Object obj) {
  34. Integer order = super.findOrder(obj);
  35. if (order != null) {
  36. return order;
  37. }
  38. return findOrderFromAnnotation(obj);
  39. }
  40. @Nullable
  41. private Integer findOrderFromAnnotation(Object obj) {
  42. AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
  43. MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
  44. Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
  45. if (order == null && obj instanceof DecoratingProxy) {
  46. return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
  47. }
  48. return order;
  49. }

总结下来就是:当我们通过构造函数或者set方法注入进某个List<类>时,Spring的DefaultListableBeanFactory类会在注入时获取AnnotationAwareOrderComparator比较器帮助我们对类进行排序,AnnotationAwareOrderComparator是OrderComparator的子类,而OrderComparator实现了比较器Comparator接口。排序的策略会先判断是否实现PriorityOrdered接口,如果没有接着会判断是否实现Order接口,此时也没有就会根据注解值进行比较。

到此这篇关于Spring @Order注解使用详解的文章就介绍到这了,更多相关Spring @Order 内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号