Spring5.1源碼閱讀記錄一

首先閱讀源碼是件很痛苦的事情。第一步整合源碼更痛苦,

參考:https://blog.csdn.net/qq_40088250/article/details/104219666

人家確實寫的不錯,可以拿來避避坑!!!

整合完成之後,新建項目進行測試。

一,Spring啓動的兩種方式

1.1 基於註解:

import com.learn.day1.AppConfig;
import com.learn.day1.AppService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

//@Configuration
@Component
public class Day2Test {


	/**
	 * 查看Spring是如何注入的
	 * @param args
	 */
    public static void main(String[] args) {
        AnnotationConfigApplicationContext
				context = new AnnotationConfigApplicationContext(Day2Test.class);
        System.out.println(context.getBean(AppService.class));

    }

    @Bean
	public AppService getService(){
    	return new AppService();
	}
}

1.2 基於xml文件:

    public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("application-day1.xml");
		System.out.println(context.getBean(AppService.class));
    }

Springcontext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xmlns="http://www.springframework.org/schema/beans"
	   xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:aop="http://www.springframework.org/schema/aop"
	   xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-4.2.xsd ">


	<!-- 掃描組件 -->
	<context:component-scan base-package="com.learn"/>


	<!-- 支持spring註解 -->
	<context:annotation-config/>
</beans>

 這裏以註解方式爲主:看懂後就要開始SpringBoot源碼學習

二:AnnotationConfigApplicationContext:Spring上下文

由下圖可知:

acx是一個讀取器:ResourseLoader

acx是一個Bean工廠:BeanFacctory

acx是一個BD註冊器:AliasRegistry

.....

* 獨立的Spring上下文
* 可以接收@Configuration 註解的類
* 或者@Compontent 註解的類

在實例化時創建了兩個對象

private final AnnotatedBeanDefinitionReader reader;BD讀取器 

private final ClassPathBeanDefinitionScanner scanner;BD掃描器

 

當創建AnnotationConfigApplicationContext的執行流程

	public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
		this();
		register(annotatedClasses);
		refresh();
	}

第一步:調用this()方法:

執行 GenericApplicationContext 構造方法創建Bean工廠

	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}
執行 AbstractApplicationContext構造方法創建解析器
	public AbstractApplicationContext() {
		this.resourcePatternResolver = getResourcePatternResolver();
	}

執行 DefaultResourceLoader構造方法創建CalssLoader

	public DefaultResourceLoader() {
		this.classLoader = ClassUtils.getDefaultClassLoader();
	}

 

第二步:初始化 AnnotatedBeanDefinitionReader

實例化對象 BeanDefinitionRegistry 其實就是AnnotationConfigApplicationContext       

實例化對象 BeanNameGenerator 名稱生成器

實例化對象 ScopeMetadataResolver 生成方式解析器

	public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
                //當前的註冊器就是指的是AnnotationConfigApplicationContext		
                this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}

第三步:初始化 ClassPathBeanDefinitionScanner 與第二個對象基本類似,只不過職能不同

實例化對象 BeanDefinitionRegistry 其實就是AnnotationConfigApplicationContext       

實例化對象 BeanNameGenerator 名稱生成器

實例化對象 ScopeMetadataResolver 生成方式解析器

第四步:調用register(annotatedClasses)方法

最終調用AnnotatedBeanDefinitionReader 的doRegisterBean方法用來生成AnnotatedGenericBeanDefinition

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

		AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
		if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
			return;
		}

		abd.setInstanceSupplier(instanceSupplier);
		ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
		abd.setScope(scopeMetadata.getScopeName());
		String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

		AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
		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));
				}
			}
		}
		for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
			customizer.customize(abd);
		}

		//相當於一個map 通過name 獲取BD
		BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
		definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
		BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
	}

結果生成BeanDefinitionHolder key:name value:BeanDefinition。方便通過getKey獲取

第五步:調用registerBeanDefinition方法 將BD加入到容器中

最終調用 DefaultListableBeanFactory 對象的registerBeanDefinition方法,將BD加入到BeanFactory中的map中去

截止到這裏項目中需要的BD已註冊到BeanFactory中

@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 {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				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()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

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

 

第五步:調用 refresh()方法刷新容器

三:Spring 核心 refresh()方法

// 容器刷新前的準備,設置上下文狀態,獲取屬性,驗證必要的屬性等
			prepareRefresh();

			// 獲取新的beanFactory,銷燬原有beanFactory、爲每個bean生成BeanDefinition等
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 配置標準的beanFactory,設置ClassLoader,設置SpEL表達式解析器,
			// 添加忽略注入的接口,添加bean,添加bean後置處理器等
			prepareBeanFactory(beanFactory);

			try {
				// 模板方法,此時,所有的beanDefinition已經加載,但是還沒有實例化。
				//允許在子類中對beanFactory進行擴展處理。比如添加ware相關接口自動裝配設置,添加後置處理器等,
				postProcessBeanFactory(beanFactory);


				//實例化並調用所有註冊的beanFactory後置處理器
				// (實現接口BeanFactoryPostProcessor的bean,在beanFactory標準初始化之後執行)。
				invokeBeanFactoryPostProcessors(beanFactory);

				// 實例化和註冊beanFactory中擴展了BeanPostProcessor的bean。
				registerBeanPostProcessors(beanFactory);

				// 初始化國際化工具類MessageSource
				initMessageSource();

				// 初始化事件廣播器
				initApplicationEventMulticaster();

				// 模板方法,在容器刷新的時候可以自定義邏輯,不同的Spring容器做不同的事情
				onRefresh();

				// 註冊監聽器,廣播early application events
				registerListeners();

				// 實例化剩餘的Bean。
				finishBeanFactoryInitialization(beanFactory);

				// 初始化上下文的生命週期處理器
				finishRefresh();
			}

5.1 prepareRefresh()用來設置基本信息比如環境時間啓動標識等

5.2 obtainFreshBeanFactory()獲取BeanFactory,設置刷新狀態等 。

5.3 prepareBeanFactory()方法 關聯BeanFactory當前的是上下文 classLoader設置BeanPostProcessor等。

5.4 postProcessBeanFactory()方法 允許在子類中對beanFactory進行擴展處理。比如添加後置處理器等。

5.5 invokeBeanFactoryPostProcessors()方法 實例化所有Bean並調用所有註冊的beanFactory後置處理器

5.6 registerBeanPostProcessors ()方法 實例化BeanPostProcessor

5.7 initMessageSource() 國際化設置

5.8 initApplicationEventMulticaster() 初始化ApplicationContext 監聽

5.9 onRefresh()

5.10 registerListeners() 註冊監聽器

5.11 finishBeanFactoryInitialization () 實例化剩餘的Bean

5.12 finishRefresh()初始化生命週期,刪除緩存等

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章