Spring Annotation Support 상세 소개 및 간단 한 실례
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();
}
}
위의 코드 에서 보 여 줍 니 다.우 리 는 다음 과 같은 결론 을 얻 을 수 있다.위 에 서 는 이미 Spring 이 org.spring from work.beans.factory.annotation.Required 라 는 라벨 을 실현 했다.작은 예 일 뿐 이지 만그러나 우 리 는 Spring 이하 의 가방 구조 에 따라 이것 이 Spring 이 자신의 Annotation 에 대한 매우 일반적인 실현 임 을 볼 수 있다.
위의 예 에서 나 는 Spring 이 그 자체 의 Annotation 에 대한 실현 을 알 수 있다.현재 글 에는 Exception Message 가 어떻게 전달 되 는 지 설명 되 어 있 지 않다.그러나 이것 은 본문 토론 의 범주 가 아니 므 로 관심 이 있 는 친 구 는 스스로 가서 볼 수 있다.
읽 어 주 셔 서 감사합니다. 여러분 에 게 도움 이 되 기 를 바 랍 니 다.본 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.