Spring 에서 Ordered 인터페이스 안내

15767 단어 spring자바
더 읽 기
머리말
        Spring 에서 Ordered 인 터 페 이 스 를 제공 합 니 다.Ordered 인 터 페 이 스 는 말 그대로 정렬 에 사용 된다.
        Spring 은 전략 디자인 모델 을 대량으로 사용 하 는 프레임 워 크 로 같은 인터페이스의 실현 류 가 많다 는 것 을 의미 하 므 로 반드시 우선 순위 의 문제 가 있 을 것 이다.
        그래서 Spring 은 Ordered 라 는 인 터 페 이 스 를 제공 하여 같은 인터페이스 실현 류 의 우선 순위 문 제 를 처리 했다.
 
2.Ordered 인터페이스 소개
        우선,Ordered 인터페이스의 정 의 를 살 펴 보 겠 습 니 다.
package org.springframework.core;

public abstract interface Ordered
{
  public static final int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
  public static final int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
  
  public abstract int getOrder();
}

        단 한 가지 방법:getOrder(); 2 개 변수:최고급(수치 최소)과 최저(수치 최대).
        Order Comparator 클래스:Comparator 의 비교 기 를 실현 합 니 다.
        3 개의 정적 정렬 방법 을 제공 합 니 다:sort(List>list),sort(Object[]array),sortIfNecessary(Object value).Order Comparator 에 따라 배열 과 집합 을 정렬 합 니 다.
        sortIfNecessary 방법 내부 에서 value 매개 변수 가 Object[]인지 List 유형 인지 판단 한 다음 Object[]매개 변수의 sort 방법 과 List 매개 변수의 sort 방법 으로 정렬 합 니 다.
        이 비교 기의 compare 방법 을 살 펴 보 자.
public int compare(Object o1, Object o2)
{
  return doCompare(o1, o2, null);
}

private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
  boolean p1 = o1 instanceof PriorityOrdered;
  boolean p2 = o2 instanceof PriorityOrdered;
  if ((p1) && (!p2)) {
    return -1;
  }
  if ((p2) && (!p1)) {
    return 1;
  }
  

  int i1 = getOrder(o1, sourceProvider);
  int i2 = getOrder(o2, sourceProvider);
  return i1 > i2 ? 1 : i1 < i2 ? -1 : 0;
}

private int getOrder(Object obj, OrderSourceProvider sourceProvider)
{
  Integer order = null;
  if (sourceProvider != null) {
    Object orderSource = sourceProvider.getOrderSource(obj);
    if ((orderSource != null) && (orderSource.getClass().isArray())) {
      Object[] sources = ObjectUtils.toObjectArray(orderSource);
      for (Object source : sources) {
        order = findOrder(source);
        if (order != null) {
          break;
        }
      }
    }
    else {
      order = findOrder(orderSource);
    }
  }
  return order != null ? order.intValue() : getOrder(obj);
}

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

        Priority Ordered 는 Ordered 인 터 페 이 스 를 계승 하 는 인터페이스 로 방법 이 정의 되 지 않 았 습 니 다.
package org.springframework.core;

public abstract interface PriorityOrdered
  extends Ordered
{}

이 코드 의 논리:
        1.대상 o1 이 Ordered 인터페이스 유형 이 고 o2 가 Priority Ordered 인터페이스 유형 이 라면 o2 의 우선 순 위 는 o1 보다 높다.
        2.대상 o1 이 Priority Ordered 인터페이스 유형 이 고 o2 가 Ordered 인터페이스 유형 이 라면 o1 의 우선 순 위 는 o2 보다 높다.
        3.다른 경우,만약 에 둘 다 Ordered 인터페이스 유형 이거 나 둘 다 Priority Ordered 인터페이스 유형 이 라면 Ordered 인 터 페 이 스 를 호출 하 는 getOrder 방법 으로 order 값 을 얻 을 수 있 습 니 다.order 값 이 클 수록 우선 순위 가 작 습 니 다.
간단하게 요약 하면:
        Order Comparator 비교 기 가 정렬 할 때 두 대상 중 한 대상 이 Priority Ordered 인 터 페 이 스 를 실현 하면 이 대상 의 우선 순위 가 더욱 높다.만약 에 두 대상 이 모두 Priority Ordered 나 Ordered 인터페이스의 실현 류 라면 Ordered 인터페이스의 getOrder 방법 을 비교 하여 order 값 을 얻 을 수 있 고 값 이 낮 을 수록 우선 순위 가 높다.
 
3.Ordered 인터페이스 가 Spring 에서 의 사용
        SpringMVC 를 예 로 들 면 Ordered 인터페이스의 운용 을 예 로 들 수 있다.

        이 설정 은*-dispatcher.xml 에서 정의 하면 SpringMVC 는 기본적으로 Request Mapping Handler Adapter 와 Request Mapping Handler Mapping 두 가지 종 류 를 주입 합 니 다.
        이 부분의 내용 에 대해 서 는 건물 주의 다른 블 로 그 를 참고 하 시기 바 랍 니 다.http://bijian1013.iteye.com/blog/2310236
        SpringMVC 와 기본 값 으로 Request Mapping Handler Adapter 와 Request Mapping Handler Mapping 두 종 류 를 주입 한 이상 이 두 종 류 를 다시 설정 할 수 있 습 니까?답 은 당연히 가능 하 다.
RequestMappingHandlerMapping:

  
    
    
  

RequestMappingHandlerAdapter:

  
    
      
      
        
          
            text/plain;charset=UTF-8
          
        
      
      
      
      
      
        
      
    
    
  
    
  
  
    
  
  

        우리 가 annotation-driven 과 이 두 개의 bean 을 설 정 했 을 때.Spring 용기 에는 Request Mapping Handler Adapter 2 개 와 Request Mapping Handler Mapping 2 개가 있다.
        Dispatcher Servlet 내부 에는 Handler Mapping(Request Mapping Handler Mapping 은 그 실현 클래스)집합 과 Handler Adapter(Request Mapping Handler Adapter 는 그 실현 클래스)집합 이 있다.
private List handlerMappings;

private List handlerAdapters;

        우 리 는 이 두 집합의 초기 화 코드 를 봅 시다.
private void initHandlerMappings(ApplicationContext context)
{
this.handlerMappings = null;

if (this.detectAllHandlerMappings)
{

  Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
  if (!matchingBeans.isEmpty()) {
    this.handlerMappings = new ArrayList(matchingBeans.values());
    
    AnnotationAwareOrderComparator.sort(this.handlerMappings);
  }
}
else {
  try {
    HandlerMapping hm = (HandlerMapping)context.getBean("handlerMapping", HandlerMapping.class);
    this.handlerMappings = Collections.singletonList(hm);
  }
  catch (NoSuchBeanDefinitionException localNoSuchBeanDefinitionException) {}
}
private void initHandlerAdapters(ApplicationContext context)
{
  this.handlerAdapters = null;
  
  if (this.detectAllHandlerAdapters)
  {

    Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
    if (!matchingBeans.isEmpty()) {
      this.handlerAdapters = new ArrayList(matchingBeans.values());
      
      AnnotationAwareOrderComparator.sort(this.handlerAdapters);
    }
  }
  else {
    try {
      HandlerAdapter ha = (HandlerAdapter)context.getBean("handlerAdapter", HandlerAdapter.class);
      this.handlerAdapters = Collections.singletonList(ha);
    }
    catch (NoSuchBeanDefinitionException localNoSuchBeanDefinitionException) {}
  }
  
  if (this.handlerAdapters == null) {
    this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class);
    if (this.logger.isDebugEnabled()) {
      this.logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default");
    }
  }
}

        AnnotationAware Order Comparator(Order Comparator 의 하위 클래스)비교 기 를 사용 하여 정렬 한 것 이 분명 합 니 다.
        다음은 annotation-driven 코드 가 설정 한 Request Mapping Handler Mapping 과 Request Mapping Handler Adapter 를 살 펴 보 겠 습 니 다.
WebMvcConfigurationSupport.java
@Bean
public RequestMappingHandlerMapping requestMappingHandlerMapping()
{
  RequestMappingHandlerMapping handlerMapping = createRequestMappingHandlerMapping();
  handlerMapping.setOrder(0);
  handlerMapping.setInterceptors(getInterceptors());
  handlerMapping.setContentNegotiationManager(mvcContentNegotiationManager());
  handlerMapping.setCorsConfigurations(getCorsConfigurations());
  
  PathMatchConfigurer configurer = getPathMatchConfigurer();
  if (configurer.isUseSuffixPatternMatch() != null) {
    handlerMapping.setUseSuffixPatternMatch(configurer.isUseSuffixPatternMatch().booleanValue());
  }
  if (configurer.isUseRegisteredSuffixPatternMatch() != null) {
    handlerMapping.setUseRegisteredSuffixPatternMatch(configurer.isUseRegisteredSuffixPatternMatch().booleanValue());
  }
  if (configurer.isUseTrailingSlashMatch() != null) {
    handlerMapping.setUseTrailingSlashMatch(configurer.isUseTrailingSlashMatch().booleanValue());
  }
  if (configurer.getPathMatcher() != null) {
    handlerMapping.setPathMatcher(configurer.getPathMatcher());
  }
  if (configurer.getUrlPathHelper() != null) {
    handlerMapping.setUrlPathHelper(configurer.getUrlPathHelper());
  }
  
  return handlerMapping;
}
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter()
{
  List argumentResolvers = new ArrayList();
  addArgumentResolvers(argumentResolvers);
  
  List returnValueHandlers = new ArrayList();
  addReturnValueHandlers(returnValueHandlers);
  
  RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
  adapter.setContentNegotiationManager(mvcContentNegotiationManager());
  adapter.setMessageConverters(getMessageConverters());
  adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer());
  adapter.setCustomArgumentResolvers(argumentResolvers);
  adapter.setCustomReturnValueHandlers(returnValueHandlers);
  
  if (jackson2Present) {
    List requestBodyAdvices = new ArrayList();
    requestBodyAdvices.add(new JsonViewRequestBodyAdvice());
    adapter.setRequestBodyAdvice(requestBodyAdvices);
    
    List> responseBodyAdvices = new ArrayList();
    responseBodyAdvices.add(new JsonViewResponseBodyAdvice());
    adapter.setResponseBodyAdvice(responseBodyAdvices);
  }
  
  AsyncSupportConfigurer configurer = new AsyncSupportConfigurer();
  configureAsyncSupport(configurer);
  
  if (configurer.getTaskExecutor() != null) {
    adapter.setTaskExecutor(configurer.getTaskExecutor());
  }
  if (configurer.getTimeout() != null) {
    adapter.setAsyncRequestTimeout(configurer.getTimeout().longValue());
  }
  adapter.setCallableInterceptors(configurer.getCallableInterceptors());
  adapter.setDeferredResultInterceptors(configurer.getDeferredResultInterceptors());
  
  return adapter;
}

        RequestMappingHandlerMapping 은 기본적으로 order 속성 을 0 으로 설정 하고 RequestMappingHandlerAdapter 는 order 속성 을 설정 하지 않 습 니 다.
        Request Mapping Handler Mapping 과 Request Mapping Handler Adapter 코드 에 들 어가 서 그들의 order 속성 이 어떻게 정의 되 는 지 보 겠 습 니 다.
public abstract class AbstractHandlerMethodAdapter
  extends WebContentGenerator
  implements HandlerAdapter, Ordered
{
  private int order = Integer.MAX_VALUE;

        Abstract Handler MethodAdapter 는 Request Mapping Handler Adapter 의 부류 입 니 다.
public abstract class AbstractHandlerMapping
  extends WebApplicationObjectSupport
  implements HandlerMapping, Ordered
{
  private int order = Integer.MAX_VALUE;

        Abstract Handler Mapping 은 Request Mapping Handler Mapping 의 부류 입 니 다.
        Request Mapping Handler Mapping 과 Request Mapping Handler Adapter 가 order 속성 을 설정 하지 않 았 을 때 order 속성의 기본 값 은 Integer.MAX 입 니 다.VALUE,즉 우선 순위 가 가장 낮다. 
 
PS:
        설정 되 어 있 고 사용자 정의 Request Mapping HandlerAdapter 가 설정 되 어 있 으 며 Request Mapping HandlerAdapter 의 order 값 이 설정 되 어 있 지 않 으 면 이 두 Request Mapping HandlerAdapter 의 order 값 은 모두 Integer.MAX 입 니 다.VALUE。그럼 누가 우선 순위 가 높 나 요?
        정 답:누가 먼저 정 의 했 는 지,누가 우선 순위 가 높 은 지.사용자 정의 Request Mapping HandlerAdapter 설정 전에 설정 한 Request Mapping HandlerAdapter 우선 순위 가 높 고,반대로 사용자 정의 Request Mapping HandlerAdapter 우선 순위 가 높 습 니 다.
        설정 하면 사용자 정의 Request Mapping Handler Mapping 을 설정 하고 Request Mapping Handler Mapping 의 order 값 을 설정 하지 않 았 습 니 다.그러면 설 정 된 Request Mapping Handler Mapping 의 우선 순위 가 높 습 니 다.내부 에 Request Mapping Handler Mapping 의 order,즉 0 이 설정 되 어 있 기 때 문 입 니 다.
        여러 보기 해석 기 에서 도 Ordered 인터페이스 에 사용 되 었 습 니 다.다음 과 같다.
DispatcherServlet.java
private void initViewResolvers(ApplicationContext context)
{
  this.viewResolvers = null;
  
  if (this.detectAllViewResolvers)
  {

    Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, ViewResolver.class, true, false);
    if (!matchingBeans.isEmpty()) {
      this.viewResolvers = new ArrayList(matchingBeans.values());
      
      AnnotationAwareOrderComparator.sort(this.viewResolvers);
    }
  }
  else {
    try {
      ViewResolver vr = (ViewResolver)context.getBean("viewResolver", ViewResolver.class);
      this.viewResolvers = Collections.singletonList(vr);
    }
    catch (NoSuchBeanDefinitionException localNoSuchBeanDefinitionException) {}
  }
  
  if (this.viewResolvers == null) {
    this.viewResolvers = getDefaultStrategies(context, ViewResolver.class);
    if (this.logger.isDebugEnabled()) {
      this.logger.debug("No ViewResolvers found in servlet '" + getServletName() + "': using default");
    }
  }
}

 
총화
        Spring 에서 Ordered 인터페이스의 의 미 를 이해 하고 실천 에서 이 인터페이스의 활용 을 분석 했다.
        이 Ordered 인터페이스 도 건물 주가 SpringMVC 에 여러 개의 보기 해석 기 를 설정 하 는 것 을 연 구 했 을 때 발 견 된 것 이다.예전 에는 별로 주의 하지 않 았 는데 사용자 정의 설정 의 RequestMappingHandlerAdapter 우선 순위 가 높 고 설정 의 RequestMappingHandlerAdapter 를 덮어 쓸 것 이 라 고 생각 했다.이 제 는 우선 순위 의 문 제 를 알 게 되 었 다.
 
글 의 출처:http://www.cnblogs.com/fangjian0423/p/spring-Ordered-interface.html

좋은 웹페이지 즐겨찾기