集合类自定义排序和springMVC viewResolver的顺序问题

看了springMVC的dispatcherServlet的源码,有个地方不是特别明白,一路找资料,懂了 所以需要记录一下。

关于initViewResolvers方法,我们知道springMVC里有一个视图解析器的概念。同一个项目可能会需要配置多个视图解析器。对于具有REST风格的服务器更是如此。

通过对源码的查看,视图解析器在配置时,可以设置order属性,这个值关联到视图解析器的执行顺序。值越小优先级越高,可以为负数。具体原理,我会在下面详细说明。

首先我们可以看看initViewResolvers方法:

private void initViewResolvers(ApplicationContext context) {
        this.viewResolvers = null;
        if(this.detectAllViewResolvers) {
            Map vr = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
            if(!vr.isEmpty()) {
                this.viewResolvers = new ArrayList(vr.values());
                AnnotationAwareOrderComparator.sort(this.viewResolvers);
            }
        } else {
            try {
                ViewResolver vr1 = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);
                this.viewResolvers = Collections.singletonList(vr1);
            } catch (NoSuchBeanDefinitionException var3) {
                ;
            }
        }

        if(this.viewResolvers == null) {
            this.viewResolvers = this.getDefaultStrategies(context, ViewResolver.class);
            if(this.logger.isDebugEnabled()) {
                this.logger.debug("No ViewResolvers found in servlet \'" + this.getServletName() + "\': using default");
            }
        }

    }
首先会取出 所有在ioc里注册过的viewResolver接口的实现(也就是配置的多个视图解析器),并将之放入数组中。

之后,利用AnnotationAwareOrderComparator类中sort方法进行排序,这个AnnotationAwareOrderComparator类继承了OrderComparator。而OrderComparator类通过我的研究,发现这个类在spring里运用很广泛。OrderComparator实现了Comparator接口。我们知道java集合类自定义排序正是需要实现Comparator接口。所以不难看出OrderComparator这个类是用于spring内bean排序。

public class OrderComparator implements Comparator<Object> {
    public static final OrderComparator INSTANCE = new OrderComparator();

    public OrderComparator() {
    }

    public Comparator<Object> withSourceProvider(final OrderComparator.OrderSourceProvider sourceProvider) {
        return new Comparator() {
            public int compare(Object o1, Object o2) {
                return OrderComparator.this.doCompare(o1, o2, sourceProvider);
            }
        };
    }

    public int compare(Object o1, Object o2) {
        return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
    }

    private int doCompare(Object o1, Object o2, OrderComparator.OrderSourceProvider sourceProvider) {
        boolean p1 = o1 instanceof PriorityOrdered;
        boolean p2 = o2 instanceof PriorityOrdered;
        if(p1 && !p2) {
            return -1;
        } else if(p2 && !p1) {
            return 1;
        } else {
            int i1 = this.getOrder(o1, sourceProvider);
            int i2 = this.getOrder(o2, sourceProvider);
            return i1 < i2?-1:(i1 > i2?1:0);
        }
    }

    private int getOrder(Object obj, OrderComparator.OrderSourceProvider sourceProvider) {
        Integer order = null;
        if(sourceProvider != null) {
            Object orderSource = sourceProvider.getOrderSource(obj);
            if(orderSource != null && orderSource.getClass().isArray()) {
                Object[] sources = ObjectUtils.toObjectArray(orderSource);
                Object[] var6 = sources;
                int var7 = sources.length;

                for(int var8 = 0; var8 < var7; ++var8) {
                    Object source = var6[var8];
                    order = this.findOrder(source);
                    if(order != null) {
                        break;
                    }
                }
            } else {
                order = this.findOrder(orderSource);
            }
        }

        return order != null?order.intValue():this.getOrder(obj);
    }

    protected int getOrder(Object obj) {
        Integer order = this.findOrder(obj);
        return order != null?order.intValue():2147483647;
    }

    protected Integer findOrder(Object obj) {
        return obj instanceof Ordered?Integer.valueOf(((Ordered)obj).getOrder()):null;
    }

    public Integer getPriority(Object obj) {
        return null;
    }

    public static void sort(List<?> list) {
        if(list.size() > 1) {
            Collections.sort(list, INSTANCE);
        }

    }

    public static void sort(Object[] array) {
        if(array.length > 1) {
            Arrays.sort(array, INSTANCE);
        }

    }

    public static void sortIfNecessary(Object value) {
        if(value instanceof Object[]) {
            sort((Object[])((Object[])value));
        } else if(value instanceof List) {
            sort((List)value);
        }

    }

    public interface OrderSourceProvider {
        Object getOrderSource(Object var1);
    }
}


它实现了compare方法,并通过findOrder方法,得到viewResolver的order属性(在配置文件里设置的order值),这里的order在spring.core包里是一个接口类,规定了order的最大值与最小值,各个viewResolver的实现类(也可以是其他bean)各自实现自己的getOrder方法。通过查看viewResolver的一些实现类,我发现若bean实现了order接口且配置bean时没设置order值,默认则是最高优先级值 -2147483648。


关于java集合类的排序再啰嗦两句。

java的集合类 collection 都会有一个sort方法,查看Collection类的源码,发现两个关键sort方法,

一个是只有一个参数的sort方法,要求返回的泛型需继承Comparable。可以重写Comparable里的compareTo方法来定义排序规则

另一个是带有两个参数的sort方法,其中第二个参数为自定义的排序器类的实例对象,这个类需要实现Comparator接口,这个排序器的用法就很多样了,支持灵活的自定义排序。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值