spring源码学习(一)——ioc初始化

spring源码学习(二)——ConfigurationClassPostProcessor(BeanFactory后置处理器的执行)
spring源码学习(三)——初始化bean
spring源码学习(四)——aop
spring两个重要的概念ioc和aop,整个框架是非常复杂的。下面主要了解一下,他们大致的一个流程。

1.1 BeanFactory和ApplicationContext

BeanFactory是spring 的顶层容器,他定义了所有ioc容器必须遵从的原则,拥有实例化对象和获取对象的功能。而ApplicationContext是他的子类,增加了很多额外的功能。不同的实现也增加了不一样的功能,Spring IoC 容器继承体系⾮常聪明,需要使⽤哪个层次⽤哪个层次即可,不必使⽤功能⼤⽽全。

1.2 初始化ioc

本文介绍spring的版本为5.2.3,ioc的初始化主要以ClasspathXmlApplicationContext为例。从创建ClassPathXmlApplicationContext开始看看ioc的整个初始化大致的流程。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
public ClassPathXmlApplicationContext(
			String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
			throws BeansException {
		//初始化父类
		super(parent);
		//设置本地的配置信息(解析配置文件给定路径替换占位符等)
		setConfigLocations(configLocations);
		//完成spring容器的初始化
		if (refresh) {
			refresh();
		}
	}

整个容器的初始化流程都在refresh方法里,下面看看AbstractApplicationContext#refresh方法

		public void refresh() {
			synchronized (this.startupShutdownMonitor) {
				// 刷新前的预处理,准备环境
				prepareRefresh();

				// 获取BeanFactory,加载注册BeanDefinition
				ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

				// BeanFactory的预准备工作
				prepareBeanFactory(beanFactory);

				// BeanFactory准备工作完成后进行的后置处理工作,子类实现
				postProcessBeanFactory(beanFactory);

				// 实例化实现了BeanFactoryPostProcessor接口的Bean,并调用接口方法
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册BeanPostProcessor(Bean的后置处理器)
				registerBeanPostProcessors(beanFactory);

				// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析)
				initMessageSource();

				// 初始化事件派发器.
				initApplicationEventMulticaster();

				// 子类重写这个方法,在容器刷新的时候可以自定义逻辑,如创建tomcat,jetty等web服务器
				onRefresh();

				// 注册实现了ApplicationListener接口的监听器bean
				registerListeners();

				// 初始化所有剩下的非懒加载的单例bean
				finishBeanFactoryInitialization(beanFactory);

				// 完成context的刷新,并且发布事件(ContextRefreshedEvent)
				finishRefresh();
			}

可以看到spring将每个功能都做了封装,在这个方法中,逻辑层次非常明了,大致流程也备注了,下面来看看几个重要的方法都具体做了什么。

1.2.1 获取BeanFactory加载注册BeanDefinition

首先看AbstractApplicationContext#obtainFreshBeanFactory 方法

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

在refreshBeanFactory()方法后就返回一个beanFactory了。主要的逻辑就在AbstractRefreshableApplicationContext#refreshBeanFactory中了。

	protected final void refreshBeanFactory() throws BeansException {
			//实例化 DefaultListableBeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 设置序列化id
			beanFactory.setSerializationId(getId());
			//自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
			customizeBeanFactory(beanFactory);
			// 加载应用中的BeanDefinitions
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				this.beanFactory = beanFactory;
			}
	
	}

这里实例化了一个DefaultListableBeanFactory并设置一些属性,然后加载应用中的BeanDefinitions,具体看看AbstractXmlApplicationContext#loadBeanDefinitions()方法

	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		//给指定的beanFactory创建一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		
		//给xmlBeanDefinitionReader对象设置一些context上下文中的环境属性
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

		//提供给子类实现提供一些自定义的初始化策略
		initBeanDefinitionReader(beanDefinitionReader);
		//真正的去加载BeanDefinitions
		loadBeanDefinitions(beanDefinitionReader);
	}
	protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
		//从Resource资源对象加载BeanDefinitions
		Resource[] configResources = getConfigResources();
		if (configResources != null) {
			reader.loadBeanDefinitions(configResources);
		}
		//从xml配置文件加载BeanDefinition对象
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			reader.loadBeanDefinitions(configLocations);
		}
	}

这里我们用的是xml的配置文件所以走下面的loadBeanDefinitions,接着将配置文件转换成resource资源对象,读取xml信息保存到Document对象中,最后调用XmlBeanDefinitionReader#registerBeanDefinitions方法解析Document为BeanDefinition

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//获取已有BeanDefinition的数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//注册BeanDefinition
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//返回新注册的BeanDefinition数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

将Document解析成BeanDefinition并注册,最后是由DefaultBeanDefinitionDocumentReader#parseBeanDefinitions方法进行

	protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//对beans的处理
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					//判断element标签是不是默认标签比如bean import alias beans标签
					if (delegate.isDefaultNamespace(ele)) {
						//解析默认标签元素
						parseDefaultElement(ele, delegate);
					}
					else {
						//解析自定义标签根据命名空间获取对应处理器解析
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}
	private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		// import元素处理
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		//alias元素处理
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
//		bean元素处理
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
//		嵌套beans处理
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse递归调用
			doRegisterBeanDefinitions(ele);
		}
	}

这里主要是了解BeanDefinition的解析与注册,所以再继续看processBeanDefinition方法

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//解析bean元素为BeanDefinition,但是此时使用BeanDefinitionHolder又包装成了BeanDefinitionHolder对象持有BeanDefinition
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
//如果有自定义标签,解析自定义标签,找到命名空间找到对应处理器,进行处理装饰
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				//完成BeanDefinition的注册
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

可以看到解析是在BeanDefinitionParserDelegate#parseBeanDefinitionElement()中进行的,创建一个GenericBeanDefinition对象,解析设置各种参数属性。BeanDefinitionReaderUtils#registerBeanDefinition则是完成BeanDefinitions的注册。

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}

获取beanName然后注册到BeanDefinitionRegistry中,具体可以看DefaultListableBeanFactory#registerBeanDefinition方法,首先会检查beanName是否已经注册,如果已经注册而且不允许覆盖直接抛出异常,接着会将BeanDefinition放入beanDefinitionMap,key就是beanName。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值