Spring5.1源码阅读记录一 - 初次见面

首先阅读源码是件很痛苦的事情。第一步整合源码更痛苦,

我这里有整合好的一份,如果不嫌弃可以直接拿来用:https://github.com/ma1013789753/Spring5.1

整合完成之后,新建项目进行测试。

一,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 其实就是个容器

实例化对象 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中去

截止到项目中仅仅注册了Spring需要的内部Bean,以及我们的配置类!

@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()初始化生命周期,删除缓存等

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值