spring 소스 코드 시리즈 (3) AnnotationConfigapplicationContext 초기 화 분석

약술 하 다
AnnotationConfigApplicationContext spring          , AnnotationConfigApplicationContext       ,     bean       。

초기 화 과정 에서 관련 된 중요 한 클래스 와 속성:
클래스 또는 속성
묘사 하 다.
AnnotationConfigApplicationContext 
spring 상하 문 환경
GenericApplicationContext  
AnnotationConfigApplicationContext  부 류 는 이곳 에서 화학 공장 을 시작 할 것 이다.
DefaultListableBeanFactory
spring bean 공장, bean 창설 에 사용
beanDefinitionMap
DefaultListable BeanFactory 의 속성 은 BeanDefinition 을 저장 하 는 데 사 용 됩 니 다. bean name 을 key 로 하고 BeanDefinition 을 value 로 합 니 다.
beanDefinitionNames
list 집합, 모든 bean 저장 name
BeanDefinition
jdk 의 class 클래스 와 비슷 합 니 다. bean 의 클래스 를 묘사 하 는 데 사 용 됩 니 다. beanClassName, scope, lazyIni, dependsOn 등 속성 이 있 습 니 다.
AnnotatedBeanDefinitionReader
주 해 를 추가 한 bean 을 읽 기 위해 읽 은 데 이 터 를 BeanDefinition 에 저장 합 니 다.
BeanDefinitionRegistry
등록 기 는 BeanDefinition 등록 을 Default Listable BeanFactory 에 저장 하 는 데 사 용 됩 니 다. 또한 reader 에서 초기 화 할 때 AnnotationConfigApplication Context 대상 자체 가 들 어 오기 때문에 AnnotationConfigApplication Context 환경 과 같 습 니 다.
 
 
 
 
 
2. 소스 코드 분석
1. AnnotationConfigApplication Context 구조 방법
AnnotationConfigApplication Context 는 네 가지 구조 방법 을 제공 합 니 다. 구체 적 인 코드 는 다음 과 같 습 니 다.
/**
 *       AnnotationConfigApplicationContext, spring  ,       ,       
 *
 */
public AnnotationConfigApplicationContext() {
	/**
	 *      AnnotatedBeanDefinition   ,          bean,
	 *         AnnotatedBeanDefinition
	 */
	this.reader = new AnnotatedBeanDefinitionReader(this);
	/**
	 *         ,             ,       bean     AnnotatedBeanDefinition
	 */
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
	super(beanFactory);
	this.reader = new AnnotatedBeanDefinitionReader(this);
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

public AnnotationConfigApplicationContext(Class>... componentClasses) {
	/**
	 *           this  ,      super()
	 */
	this();
	/**
	 *     bean,          ,         bean
	 *
	 */
	register(componentClasses);
	refresh();
}


public AnnotationConfigApplicationContext(String... basePackages) {
	this();
	scan(basePackages);
	refresh();
}

주의해 야 할 것 은 무 참 구조 방법 을 사용 할 경우 register () 또는 scan () 방법 을 수 동 으로 호출 해 야 하 며, 마지막 으로 refresh () 방법 이 필요 하 다 는 점 이다. 본 고 는 Public AnnotationConfigApplication Context (Class >... componentClasses) 를 예 로 들 어 분석 하고 자 한다.이 구조 방법 은 세 부분 으로 나 눌 수 있다.
                                   1)this
                                   2)register()
                                   3)refresh()
2. this()
하위 구조 방법 을 집행 할 때 먼저 부류 구조 방법, 즉 this () 방법의 집행 이 먼저 부류 의 구조 방법 을 집행 한다 면 부류 구조 방법 부터 살 펴 보 자.
AnnotationConfigApplicationContext GenericApplicationContext 에서 계승
public GenericApplicationContext() {
	/**
	 *         ,    bean  
	 * @reviewer wangcongming
	 */
	this.beanFactory = new DefaultListableBeanFactory();
}

GenericApplication Context 에서 공장 클래스 Default Listable Bean Factory 를 초기 화 했 습 니 다.다음은 DefaultListableBeanFactory 의 중요 한 속성 을 간단하게 보 여 줍 니 다. 그 중에서 beanDefinitionMap 은 BeanDefinition (bean 의 클래스 설명) 을 저장 하 는 데 사 용 됩 니 다. beanDefinitionNames 는 모든 bean name 을 저장 하 는 데 사 용 됩 니 다.
/**
 *     
 * @reviewer wangcongming
 */
@Nullable
private Comparator dependencyComparator;

/**
 *        
 * @reviewer wangcongming
 */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();

/**
 *   
 * @reviewer wangcongming
 */
private final Map, Object> resolvableDependencies = new ConcurrentHashMap<>(16);

/**
 * spring  ,    BeanDefinition(  bean  )
 * @reviewer wangcongming
 */
private final Map beanDefinitionMap = new ConcurrentHashMap<>(256);

/**
 * class bean name    
 * @reviewer wangcongming
 */
private final Map, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);

/**
 *    class bean name    
 * @reviewer wangcongming
 */
private final Map, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);

/**
 *     bean name
 * @reviewer wangcongming
 */
private volatile List beanDefinitionNames = new ArrayList<>(256);

부모 클래스 구조 가 완료 되면 하위 클래스 (AnnotationConfigApplication Context) 의 초기 화 를 볼 수 있 습 니 다.
/**
 *      AnnotatedBeanDefinition   ,          bean,
 *         AnnotatedBeanDefinition
 */
this.reader = new AnnotatedBeanDefinitionReader(this);
/**
 *         ,             ,       bean     AnnotatedBeanDefinition
 */
this.scanner = new ClassPathBeanDefinitionScanner(this);

이 를 통 해 알 수 있 듯 이 AnnotationConfigApplication Context 의 무 참 구조 에서 두 가지 일 만 했 고 하나의 리더 (Annotated Bean DefinitionReader) 와 하나의 스캐너 (ClassPathBean DefinitionScanner) 를 초기 화 했다.
리더 AnnotatedBeanDefinitionReader
말 그대로 판독 기 는 bean 을 읽 는 데 사 용 됩 니 다. bean 을 읽 어서 BeanDefinition 대상 을 만 드 는 역할 을 합 니 다. 마지막 으로 BeanDefinition 대상 을 Default Listable BeanFactory 의 beanDefinitionMap 에 저장 합 니 다.
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	Assert.notNull(environment, "Environment must not be null");
	this.registry = registry;
	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

AnnotationConfigApplication Context 에서 리더 기 를 만 들 때 this 즉 대상 자 체 를 들 여 옵 니 다. Annotated Bean DefinitionReader 에 서 는 Bean DefinitionRegistry 를 사용 하여 받 습 니 다. 그러면 Bean DefinitionRegistry 는 AnnotationConfigApplication Context 와 같 고 모두 spring 용기 의 컨 텍스트 환경 이 라 고 볼 수 있 습 니 다.그럼 빈 데 피 니 션 레 지 스 트 리 는 뭐 하 는 거 예요?실제로 Bean Definition Registry 는 bean 을 등록 하 는 데 사용 되 는 등록 기 입 니 다.Annotated BeanDefinitionReader 에서 읽 은 BeanDefinition 은 BeanDefinitionRegistry 를 통 해 Default Listable BeanFactory 에 등 록 된 beanDefinitionMap 입 니 다.
이 구조 방법 은 최종 적 으로 AnnotationConfigUtils. registerAnnotationConfigProcessors (this. registry) 에 의뢰 합 니 다.뭔 가 를 했 어 요.
/**
 *         
 */
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
	registerAnnotationConfigProcessors(registry, null);
}

public static Set registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {

	// registry   DefaultListableBeanFactory
	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	//     
	if (beanFactory != null) {
		//set    
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
		// set      
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set beanDefs = new LinkedHashSet<>(8);
	//       spring     bean,          ,      
	//ConfigurationClassPostProcessor        
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	//AutowiredAnnotationBeanPostProcessor          
	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	//    JSR-250  
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	//    jpa 
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
					AnnotationConfigUtils.class.getClassLoader()));
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}

	return beanDefs;
}

스캐너 ClassPathBeanDefinitionScanner
스캐너 는 클래스 패 키 지 를 스 캔 하 는 데 사 용 됩 니 다. 주로 설정 클래스 의 @ Componentscan 주석 설정 의 속성 을 스 캔 하 는 데 사 용 됩 니 다.
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
	this(registry, true);
}
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
	this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment) {

	this(registry, useDefaultFilters, environment,
			(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	this.registry = registry;

	if (useDefaultFilters) {
		registerDefaultFilters();
	}
	setEnvironment(environment);
	setResourceLoader(resourceLoader);
}

scanner 에서 도 Bean Definition Registry 를 초기 화 한 것 을 알 수 있 습 니 다. 이 는 scanner 스 캔 류 를 스 캔 할 때 생 성 된 Bean Definition 대상 을 Default Listable Bean Factory 공장 의 bean Definition Map 에 등록 해 야 하기 때 문 입 니 다.
3. register()
public void register(Class>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	this.reader.register(componentClasses);
}

register () 방법 은 하나 이상 의 bean 을 등록 할 수 있 습 니 다. 이 bean 은 하나의 설정 류 일 수도 있 고 일반적인 bean 일 수도 있 습 니 다. 이 방법 자체 가 아무것도 하지 않 았 음 을 알 수 있 습 니 다. 진정한 등록 기능 을 reader 에 의뢰 하여 처리 합 니 다.이것 은 바로 위 에서 말 한 reader 는 bean 을 읽 고 읽 은 데 이 터 를 BeanDefinition 에 저장 하 는 데 사 용 됩 니 다.
public void register(Class>... componentClasses) {
	//    bean
	for (Class> componentClass : componentClasses) {
		registerBean(componentClass);
	}
}

public void registerBean(Class> beanClass) {
	doRegisterBean(beanClass, null, null, null);
}

 void doRegisterBean(Class beanClass, @Nullable Supplier instanceSupplier, @Nullable String name,
			@Nullable Class extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {

	/**
	 *
	 *       bean   bean class   BeanDefinition
	 * @reviewer wangcongming
	 */
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);

	//abd.getMetadata()          、     、 Class      
	//    conditionEvaluator#shouldSkip   , Class      。
	//      :   @Configuration  。      Condition  ,     ~
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(instanceSupplier);

	/**
	 *   bean    
	 * @reviewer wangcongming
	 */
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	abd.setScope(scopeMetadata.getScopeName());
	/**
	 *
	 *       bean name
	 * @reviewer wangcongming
	 */
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

	/**
	 *          
	 * @reviewer wangcongming
	 */
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

	/**
	 *     qualifiers     ,      
	 */
	if (qualifiers != null) {
		for (Class extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	/**
	 *        ,      
	 * @reviewer wangcongming
	 */
	for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
		customizer.customize(abd);
	}

	/**
	 * BeanDefinitionHolder   BeanDefinition beanName    ,    
	 * @reviewer wangcongming
	 */
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

doRegisterBean () 방법 은 bean 을 읽 고 BeanDefinition 을 map 에 저장 하 는 것 입 니 다.
코드 를 보 니 BeanDefinitionRegistry 를 사용 하여 BeanDefinition 을 factory 의 beanDefinitionMap 에 등록 하 였 습 니 다.

@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
		throws BeanDefinitionStoreException {

	Assert.hasText(beanName, "Bean name must not be empty");
	Assert.notNull(beanDefinition, "BeanDefinition must not be null");

	if (beanDefinition instanceof AbstractBeanDefinition) {
		try {
			/**
			 *      
			 * @reviewer wangcongming
			 */
			((AbstractBeanDefinition) beanDefinition).validate();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
					"Validation of bean definition failed", ex);
		}
	}

	/**
	 *  map   beanName  BeanDefinition
	 *      bean        
	 * @reviewer wangcongming
	 */
	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
	if (existingDefinition != null) {
		if (!isAllowBeanDefinitionOverriding()) {
			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
		}
		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
			if (logger.isInfoEnabled()) {
				logger.info("Overriding user-defined bean definition for bean '" + beanName +
						"' with a framework-generated bean definition: replacing [" +
						existingDefinition + "] with [" + beanDefinition + "]");
			}
		}
		else if (!beanDefinition.equals(existingDefinition)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Overriding bean definition for bean '" + beanName +
						"' with a different definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Overriding bean definition for bean '" + beanName +
						"' with an equivalent definition: replacing [" + existingDefinition +
						"] with [" + beanDefinition + "]");
			}
		}
		//          
		this.beanDefinitionMap.put(beanName, beanDefinition);
	}
	else {
		if (hasBeanCreationStarted()) {
			synchronized (this.beanDefinitionMap) {
				this.beanDefinitionMap.put(beanName, beanDefinition);
				List updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
				updatedDefinitions.addAll(this.beanDefinitionNames);
				updatedDefinitions.add(beanName);
				this.beanDefinitionNames = updatedDefinitions;
				removeManualSingletonName(beanName);
			}
		}
		else {
			/**
			 *  beanDefinition  map, beanName   beanDefinitionNames
			 * @reviewer wangcongming
			 */
			this.beanDefinitionMap.put(beanName, beanDefinition);
			this.beanDefinitionNames.add(beanName);
			removeManualSingletonName(beanName);
		}
		this.frozenBeanDefinitionNames = null;
	}

	if (existingDefinition != null || containsSingleton(beanName)) {
		//  BeanDefinition
		resetBeanDefinition(beanName);
	}
}

4) refresh()
앞부분 에 초기 화 된 환경 (사용 할 대상 초기 화) 이 준비 되 어 있 습 니 다. refresh () 방법 은 bean 및 공장 백업 프로세서 (BeanFactory PostProcessor) 를 읽 기 시작 하 는 것 입 니 다. spring 의 많은 기능 은 BeanFactory PostProcessor 를 통 해 이 루어 집 니 다. 설정 류 의 스 캔 을 포함 합 니 다.
 
계속
 
 
 
 
 
 
 
 
 
 

좋은 웹페이지 즐겨찾기