springboot 에서@Value 의 작업 원리 설명

7621 단어 springboot@Value
springboot 에 있 는 Bean 구성 요소 의 구성원 변수(속성)를 알 고 있 습 니 다.@Value 주 해 를 추가 하면 효과 적 인 설정 속성 자원 에서 설정 항목 을 찾 아 연결 할 수 있 습 니 다.그러면 이 모든 것 은 어떻게 발생 합 니까?
다음은@Value 의 작업 원 리 를 간략하게 분석 하 겠 습 니 다.
springboot 버 전:springboot-2.0.6.RELEASE
개술
springboot 시작 과정 에서 두 가지 중요 한 과정 이 있 습 니 다.다음 과 같 습 니 다.
1.용기 에 있 는 bean 을 스 캔 하여 beanFactory 에 등록 하 는 것 은 마치 정보 등록 과 같다.
2 스 캔 한 bean 을 실례 화하 고 초기 화 합 니 다.
@Value 의 해석 은 두 번 째 단계 입 니 다.BeanPostProcessor 는 bean 초기 화 전후 사용자 가 bean 을 조작 할 수 있 는 인터페이스 방법 을 정의 합 니 다.중요 한 실현 클래스 인 Autowired Annotation BeanPostProcessor 는 javadoc 가 말 한 것 처럼 bean 의@Autowired 와@Value 주해 의 주입 기능 을 지원 합 니 다.
해석 절차
호출 체인 순차 도
@Value 분석 과정 에서 주요 호출 체인 은 다음 순서 그림 으로 표시 합 니 다.
在这里插入图片描述
여기 서 먼저 그림 의 몇 가지 작용 을 간단하게 소개 합 니 다.AbstractAutowireCapableBeanFactorybean 생 성,속성 충전,자동 조립,초기 후 를 제공 합 니 다.자동 조립 구조 함 수 를 지원 하고 속성 은 이름과 유형 에 따라 조립 합 니 다.AutowireCapableBeanFactory 인터페이스 정 의 를 실현 한 createBean 방법 입 니 다.AutowiredAnnotationBeanPostProcessorbean 에 표 시 된 구성원 변수,setter 방법,임 의 설정 방법 을 사용 합 니 다.전형 적 인 것 은@Autowired 주해 와@Value 주해 입 니 다.InjectionMetadata클래스 의 주입 메타 데이터,클래스 의 방법 이나 속성 등 이 있 을 수 있 습 니 다.Autowired Annotation BeanPostProcessor 류 에서 사 용 됩 니 다.AutowiredFieldElementAutowired Annotation BeanPostProcessor 의 개인 내부 클래스 로 Injection Metadata.Injected Element 를 계승 하여 주 해 를 설명 하 는 필드 입 니 다.StringValueResolver:문자열 값 을 처리 하 는 인 터 페 이 스 를 정의 합 니 다.인터페이스 방법 인 resolve StringValue 만 있 습 니 다.자리 차지 문자 문자열 을 해결 할 수 있 습 니 다.본 논문 의 주요 실현 클래스 는 Property SourcesPlaceholder Configure\#processProperties 방법 에서 lamda 표현 식 을 통 해 정 의 됩 니 다.ConfigurableBeanFactory 클래스 에서 사용 할 수 있 습 니 다.PropertySourcesPropertyResolver속성 자원 프로세서,주요 기능 은 Property Sources 속성 자원 의 설정 키 쌍 을 가 져 오 는 것 입 니 다.PropertyPlaceholderHelper자리 표시 자 를 가 진 문자열 을 처리 하 는 도구 클래스 입 니 다.${name}과 같은 문자열 은 이 도구 류 의 도움 을 받 아 사용자 가 제공 하 는 값 으로 대체 할 수 있 습 니 다.대체 경 로 는 Properties 인 스 턴 스 나 Placeholder Resolver(내부 정의 인터페이스)를 통 해 이 루어 질 수 있 습 니 다.PropertyPlaceholderConfigurerResolver:이전 줄 에서 말 한 Placeholder Resolver 인터페이스의 실현 류 는 Property Placeholder Configure 류 의 개인 내부 류 입 니 다.구현 방법 resolve Placeholder 에서 외부 클래스 의 resolve Placeholder 방법 을 호출 하 였 습 니 다.
호출 체인 설명
여기 서 주로 체인 을 호출 하 는 비교적 중요 한 방법 을 소개 한다.
AbstractAutowireCapableBeanFactory\#populateBean 방법 은 bean 속성 을 채 우 는 데 사용 되 며,실행 후 속성 조립 후의 bean 을 얻 을 수 있 습 니 다.

protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) {       
...
if (hasInstAwareBpps) {
	//     InstantiationAwareBeanPostProcessor         。
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		// AutowiredAnnotationBeanPostProcessor      
		if (bp instanceof InstantiationAwareBeanPostProcessor) {
			InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
			pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
		//       ,bw.getWrappedInstance()    @Value        bean 
			if (pvs == null) {
				return;
			}
		}
	}
}
...
}
InjectionMetadata\#inject 는 bean 의 설정 속성 을 하나씩 조립 합 니 다.

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
	    //       
		for (InjectedElement element : elementsToIterate) {
			if (logger.isDebugEnabled()) {
				logger.debug("Processing injected element of bean '" + beanName + "': " + element);
			}
			element.inject(target, beanName, pvs);
		}
	}
}
PropertyPlaceholder Helper\#parseStringValue 분석 속성 값

/**
 *         value = "${company.ceo}"
 *
 */
protected String parseStringValue(
		String value, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) {
	StringBuilder result = new StringBuilder(value);
	// this.placeholderPrefix = "${"
	int startIndex = value.indexOf(this.placeholderPrefix);
	while (startIndex != -1) {
		//         , value = "${company.ceo}"  ,endIndex=13
		int endIndex = findPlaceholderEndIndex(result, startIndex);
		if (endIndex != -1) {
			//   {}        ,   "company.ceo"
			String placeholder = result.substring(startIndex + this.placeholderPrefix.length(), endIndex);
			String originalPlaceholder = placeholder;
			if (!visitedPlaceholders.add(originalPlaceholder)) {
				throw new IllegalArgumentException(
						"Circular placeholder reference '" + originalPlaceholder + "' in property definitions");
			}
			// Recursive invocation, parsing placeholders contained in the placeholder key.
			//        ,              
			placeholder = parseStringValue(placeholder, placeholderResolver, visitedPlaceholders);
			// Now obtain the value for the fully resolved key...
			//      placeholder      
			String propVal = placeholderResolver.resolvePlaceholder(placeholder);
			//       company.ceo=${bi:li} ,company.ceo   li      
			//        ,        ${}   ,        spring     
			if (propVal == null && this.valueSeparator != null) {
				int separatorIndex = placeholder.indexOf(this.valueSeparator);
				if (separatorIndex != -1) {
					String actualPlaceholder = placeholder.substring(0, separatorIndex);
					String defaultValue = placeholder.substring(separatorIndex + this.valueSeparator.length());
					propVal = placeholderResolver.resolvePlaceholder(actualPlaceholder);
					if (propVal == null) {
						propVal = defaultValue;
					}
				}
			}
			if (propVal != null) {
				// Recursive invocation, parsing placeholders contained in the
				// previously resolved placeholder value.
				propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
				//  ${company.ceo}   li
				result.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
				if (logger.isTraceEnabled()) {
					logger.trace("Resolved placeholder '" + placeholder + "'");
				}
				startIndex = result.indexOf(this.placeholderPrefix, startIndex + propVal.length());
			}
			else if (this.ignoreUnresolvablePlaceholders) {
				// Proceed with unprocessed value.
				startIndex = result.indexOf(this.placeholderPrefix, endIndex + this.placeholderSuffix.length());
			}
			else {
				throw new IllegalArgumentException("Could not resolve placeholder '" +
						placeholder + "'" + " in value \"" + value + "\"");
			}
			visitedPlaceholders.remove(originalPlaceholder);
		}
		else {
			startIndex = -1;
		}
	}
	return result.toString();
}
총결산
@Value 주석 에 표 시 된 bean 속성 조립 은 Autowired Annotation BeanPostProcessor 에 의 해 bean 의 예화,초기 화 단계 에서 이 루어 졌 습 니 다.이상 은 개인 적 인 경험 이 므 로 여러분 에 게 참고 가 되 기 를 바 랍 니 다.여러분 들 도 저 희 를 많이 응원 해 주시 기 바 랍 니 다.

좋은 웹페이지 즐겨찾기