Spring Annotation Support 상세 소개 및 간단 한 실례

15572 단어 SpringAnnotaionSupport
최근 스프링 홈 페이지 를 보고 있다.스프링 IOC 를 보다 가 스프링 용기 확장 점 을 보다 가 빈 포스트 프로세서 라 는 인 터 페 이 스 를 발견 했다.다음은 공식 적 으로 그것 에 대한 상세 한 설명 이다.
          BeanPostProcessor 인 터 페 이 스 는 리 셋 방법 을 정의 합 니 다.사용 자 는 자신의(또는 용 기 를 덮어 쓰 는 기본)실례 화 논리,의존성 해석 논리 등 을 실현 할 수 있 습 니 다.사용자 정의 논리 Spring 용기 의 예화 가 완료 되면 bean 을 설정 하고 초기 화 하려 면 하나 이상 의 BeanPostProcessor 를 삽입 할 수 있 습 니 다.
          여러 개의 BeanPostProcessor 인 스 턴 스 를 설정 할 수 있 습 니 다.제어 할 수 있 는 순 서 는 이 BeanPostProcessors 를 통 해 속성 을 설정 할 수 있 습 니 다.이 속성 을 설정 할 수 있 습 니 다.BeanPostProcessor 만 명령 인 터 페 이 스 를 실현 합 니 다.만약 당신 이 자신의 BeanPost Processor 를 쓴다 면 당신 도 the Ordered 인 터 페 이 스 를 실현 하 는 것 을 고려 해 야 합 니 다.자세 한 내용 은 빈 포스트 프로세서 의 자바 doc 와 명령 인터페이스 에 문의 하 십시오.
          빈 포스트 프로세서 에는 두 가지 방법 이 있다.
          BeanPostProcessor 인 터 페 이 스 를 실현 하 는 종 류 는 용기 가 특수 하고 구별 된다.모든 BeanPostProcessors 와 그들 은 시작 할 때 실례 화 된 bean 을 직접 인용 하여 특수 한 응용 프로그램 Context 의 시작 단계 로 한다.이 어 모든 BeanPost Processors are 등록 분류 방식 은 모든 진일보 한 bean 용기 에 적용 된다.AOP auto-proxying aBeanPostProcessor 자 체 를 실현 하기 때문에 BeanPostProcessors 든 beas 든 그들 은 auto-proxyng 의 직접 인용 을 받 을 자격 이 있 기 때문에 편성 할 부분 이 없다.
          BeanPostProcessor 인 터 페 이 스 를 실현 하 는 종 류 는 용기 가 특수 하고 구별 된다.모든 BeanPostProcessors 와 그들 은 시작 할 때 실례 화 된 bean 을 직접 인용 하여 특수 한 응용 프로그램 Context 의 시작 단계 로 한다.이 어 모든 BeanPost Processors are 등록 분류 방식 은 모든 진일보 한 bean 용기 에 적용 된다.AOP auto-proxying aBeanPostProcessor 자 체 를 실현 하기 때문에 BeanPostProcessors 든 beas 든 그들 은 auto-proxyng 의 직접 인용 을 받 을 자격 이 있 기 때문에 편성 할 부분 이 없다.
          리 셋 인터페이스 나 주석 과 사용자 정의 로 BeanPostProcessor 를 실현 하 는 것 은 흔히 볼 수 있 는 확장 SpringIoC 용기 입 니 다.RequiredAnnotationBeanPostProcessor 는 Spring 의 한 예 입 니 다.BeanPostProcessor 에 첨부 된 Spring 분 포 를 실현 하고 자바 빈 속성 bean 에 주석(임 의)이 표시 되 어 있 는 지 확인 합 니 다.
위 에 AOP 라 는 Spring 의 두 가지 특성 중 하 나 를 보 자마자 마음 이 설 레 었 다 고?뒤에 스프링 의 Annotation 을 하나 더 하 는 것 도 보통 이 인터페이스 로 이 루어 진다.이제 못 참 겠 어 요.Required Annotation Bean Post Processor 같은 게 뭘 했 는 지 보고 싶 어 요.직접 소스 코드

Spring Annotation Support 
 
/* 
 * Copyright 2002-2013 the original author or authors. 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License. 
 */ 
 
package org.springframework.beans.factory.annotation; 
 
import java.beans.PropertyDescriptor; 
import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.List; 
import java.util.Set; 
import java.util.concurrent.ConcurrentHashMap; 
 
import org.springframework.beans.BeansException; 
import org.springframework.beans.PropertyValues; 
import org.springframework.beans.factory.BeanFactory; 
import org.springframework.beans.factory.BeanFactoryAware; 
import org.springframework.beans.factory.BeanInitializationException; 
import org.springframework.beans.factory.config.BeanDefinition; 
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter; 
import org.springframework.beans.factory.support.MergedBeanDefinitionPostProcessor; 
import org.springframework.beans.factory.support.RootBeanDefinition; 
import org.springframework.core.Conventions; 
import org.springframework.core.Ordered; 
import org.springframework.core.PriorityOrdered; 
import org.springframework.core.annotation.AnnotationUtils; 
import org.springframework.util.Assert; 
 
/** 
 * {@link org.springframework.beans.factory.config.BeanPostProcessor} implementation 
 * that enforces required JavaBean properties to have been configured. 
 *     JavaBean   properties        
 * Required bean properties are detected through a Java 5 annotation: 
 *    bean    Java 5  annotation      
 * by default, Spring's {@link Required} annotation. 
 * 
 * <p>The motivation for the existence of this BeanPostProcessor is to allow 
 * BeanPostProcessor         
 * developers to annotate the setter properties of their own classes with an 
 * arbitrary JDK 1.5 annotation to indicate that the container must check 
 * for the configuration of a dependency injected value. This neatly pushes 
 *       setter              JDK 1.5                  。 
 * responsibility for such checking onto the container (where it arguably belongs), 
 *        check     Spring  (       ) 
 * and obviates the need (<b>in part</b>) for a developer to code a method that 
 * simply checks that all required properties have actually been set. 
 *                                properties         
 * <p>Please note that an 'init' method may still need to implemented (and may 
 * still be desirable), because all that this class does is enforce that a 
 *                 (        ) 
 * 'required' property has actually been configured with a value. It does 
 *       Class      'required'            
 * <b>not</b> check anything else... In particular, it does not check that a 
 *     check    ,    ,   check         null  
 * configured value is not {@code null}. 
 * 
 * <p>Note: A default RequiredAnnotationBeanPostProcessor will be registered 
 * by the "context:annotation-config" and "context:component-scan" XML tags. 
 *      "context:annotation-config"  "context:component-scan"XML        RequiredAnnotationBeanPostProcessor 
 * Remove or turn off the default annotation configuration there if you intend 
 * to specify a custom RequiredAnnotationBeanPostProcessor bean definition. 
 *              RequiredAnnotationBeanPostProcessor bean             annotation   
 * 
 * @author Rob Harrop 
 * @author Juergen Hoeller 
 * @since 2.0 
 * @see #setRequiredAnnotationType 
 * @see Required 
 */ 
public class RequiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter 
    implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { 
 
  /** 
   * Bean definition attribute that may indicate whether a given bean is supposed 
   * to be skipped when performing this post-processor's required property check. 
   *   bean          post-processor(     )  check   bean       
   * @see #shouldSkip 
   */ 
  public static final String SKIP_REQUIRED_CHECK_ATTRIBUTE = 
      Conventions.getQualifiedAttributeName(RequiredAnnotationBeanPostProcessor.class, "skipRequiredCheck"); 
 
 
  private Class<? extends Annotation> requiredAnnotationType = Required.class; 
 
  private int order = Ordered.LOWEST_PRECEDENCE - 1; 
 
  private ConfigurableListableBeanFactory beanFactory; 
 
  /** 
   * Cache for validated bean names, skipping re-validation for the same bean 
   *         bean  ,       bean 
   */ 
  private final Set<String> validatedBeanNames = 
      Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>(64)); 
 
 
  /** 
   * Set the 'required' annotation type, to be used on bean property 
   * setter methods. 
   *          ,  bean  setter   
   * <p>The default required annotation type is the Spring-provided 
   * {@link Required} annotation. 
   *      required annotation   Spring   annotation 
   * <p>This setter property exists so that developers can provide their own 
   * (non-Spring-specific) annotation type to indicate that a property value 
   * is required. 
   *       property               annotaion                
   */ 
  public void setRequiredAnnotationType(Class<? extends Annotation> requiredAnnotationType) { 
    Assert.notNull(requiredAnnotationType, "'requiredAnnotationType' must not be null"); 
    this.requiredAnnotationType = requiredAnnotationType; 
  } 
 
  /** 
   * Return the 'required' annotation type. 
   */ 
  protected Class<? extends Annotation> getRequiredAnnotationType() { 
    return this.requiredAnnotationType; 
  } 
 
  @Override 
  public void setBeanFactory(BeanFactory beanFactory) { 
    if (beanFactory instanceof ConfigurableListableBeanFactory) { 
      this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; 
    } 
  } 
 
  public void setOrder(int order) { 
    this.order = order; 
  } 
 
  @Override 
  public int getOrder() { 
    return this.order; 
  } 
 
 
  @Override 
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { 
  } 
 
  @Override 
  public PropertyValues postProcessPropertyValues( 
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) 
      throws BeansException { 
    //           bean validated 
    if (!this.validatedBeanNames.contains(beanName)) { 
      //     
      if (!shouldSkip(this.beanFactory, beanName)) { 
        List<String> invalidProperties = new ArrayList<String>(); 
        for (PropertyDescriptor pd : pds) { 
          //        required            (       ) 
          if (isRequiredProperty(pd) && !pvs.contains(pd.getName())) { 
            //        
            invalidProperties.add(pd.getName()); 
          } 
        } 
        // <span style="color:#ff0000;">     properties   。    </span> 
        if (!invalidProperties.isEmpty()) { 
          throw new BeanInitializationException(buildExceptionMessage(invalidProperties, beanName)); 
        } 
      } 
      //       bean       
      this.validatedBeanNames.add(beanName); 
    } 
    return pvs; 
  } 
 
  /** 
   * Check whether the given bean definition is not subject to the annotation-based 
   * required property check as performed by this post-processor. 
   *   post-processor(     )           bean         check   property    
   * <p>The default implementations check for the presence of the 
   * {@link #SKIP_REQUIRED_CHECK_ATTRIBUTE} attribute in the bean definition, if any. 
   *        check  SKIP_REQUIRED_CHECK_ATTRIBUTE        bean 
   * It also suggests skipping in case of a bean definition with a "factory-bean" 
   * reference set, assuming that instance-based factories pre-populate the bean. 
   *             bean   "factory-bean"  ,         factories     bean 
   * @param beanFactory the BeanFactory to check against 
   * @param beanName the name of the bean to check against 
   * @return {@code true} to skip the bean; {@code false} to process it 
   *      true    bean,  false     
   */ 
  protected boolean shouldSkip(ConfigurableListableBeanFactory beanFactory, String beanName) { 
    //     beanFacotry      bean            bean  。  false 
    if (beanFactory == null || !beanFactory.containsBeanDefinition(beanName)) { 
      return false; 
    } 
    BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); 
    //     bean   beanName,    null,  true 
    if (beanDefinition.getFactoryBeanName() != null) { 
      return true; 
    } 
    Object value = beanDefinition.getAttribute(SKIP_REQUIRED_CHECK_ATTRIBUTE); 
    return (value != null && (Boolean.TRUE.equals(value) || Boolean.valueOf(value.toString()))); 
  } 
 
  /** 
   * Is the supplied property required to have a value (that is, to be dependency-injected)? 
   *           propery      (        )? 
   * <p>This implementation looks for the existence of a 
   * {@link #setRequiredAnnotationType "required" annotation} 
   * on the supplied {@link PropertyDescriptor property}. 
   *             ProertyDescriptor    "required"   
   * @param propertyDescriptor the target PropertyDescriptor (never {@code null}) 
   * @return {@code true} if the supplied property has been marked as being required; 
   *   true,     property         </span> 
   * {@code false} if not, or if the supplied property does not have a setter method 
   *   false,               property    setter   
   */ 
  protected boolean isRequiredProperty(PropertyDescriptor propertyDescriptor) { 
    Method setter = propertyDescriptor.getWriteMethod(); 
    return (setter != null && AnnotationUtils.getAnnotation(setter, getRequiredAnnotationType()) != null); 
  } 
 
  /** 
   * Build an exception message for the given list of invalid properties. 
   *        properties        
   * @param invalidProperties the list of names of invalid properties 
   * @param beanName the name of the bean 
   * @return the exception message 
   */ 
  private String buildExceptionMessage(List<String> invalidProperties, String beanName) { 
    int size = invalidProperties.size(); 
    StringBuilder sb = new StringBuilder(); 
    sb.append(size == 1 ? "Property" : "Properties"); 
    for (int i = 0; i < size; i++) { 
      String propertyName = invalidProperties.get(i); 
      if (i > 0) { 
        if (i == (size - 1)) { 
          sb.append(" and"); 
        } 
        else { 
          sb.append(","); 
        } 
      } 
      sb.append(" '").append(propertyName).append("'"); 
    } 
    sb.append(size == 1 ? " is" : " are"); 
    sb.append(" required for bean '").append(beanName).append("'"); 
    return sb.toString(); 
  } 
 
} 
위의 코드 에서 보 여 줍 니 다.우 리 는 다음 과 같은 결론 을 얻 을 수 있다.
111
위 에 서 는 이미 Spring 이 org.spring from work.beans.factory.annotation.Required 라 는 라벨 을 실현 했다.작은 예 일 뿐 이지 만그러나 우 리 는 Spring 이하 의 가방 구조 에 따라 이것 이 Spring 이 자신의 Annotation 에 대한 매우 일반적인 실현 임 을 볼 수 있다.
11
위의 예 에서 나 는 Spring 이 그 자체 의 Annotation 에 대한 실현 을 알 수 있다.현재 글 에는 Exception Message 가 어떻게 전달 되 는 지 설명 되 어 있 지 않다.그러나 이것 은 본문 토론 의 범주 가 아니 므 로 관심 이 있 는 친 구 는 스스로 가서 볼 수 있다.
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기