spring初始化refresh()之obtainFreshBeanFactory()

1.obtainFreshBeanFactory()

该方法会调用org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();//刷新 bean factory,进入此方法查看
		return getBeanFactory();
	}

2.refreshBeanFactory()

该方法,有两个实现,进入org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory

@Override
	protected final void refreshBeanFactory() throws BeansException {
		// 1.判断是否已有bean factory
        if (hasBeanFactory()) {
			destroyBeans();// 销毁 beans
			closeBeanFactory();// 关闭 bean factory
		}
		try {
			// 2.实例化 DefaultListableBeanFactory
			DefaultListableBeanFactory beanFactory = createBeanFactory();
			// 3. 设置序列化id 并建立起id和该 bean factory 实例的映射关系
			beanFactory.setSerializationId(getId());
			// 4.自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)
			customizeBeanFactory(beanFactory);
			//TODO  5.加载应用中的BeanDefinitions
			loadBeanDefinitions(beanFactory);
			synchronized (this.beanFactoryMonitor) {
				// 赋值当前bean facotry
				this.beanFactory = beanFactory;
			}
		}
		catch (IOException ex) {
			throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
		}
	}

2.1 首先判断是否存在BeanFactory,如果存在则销毁并关闭BeanFactory

2.2 然后在实例化BeanFactory,这里实现的是DefaultListableBeanFactory

2.3 设置序列化ID,与BeanFactory建立映射关系

2.4 自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖)

2.5 加载应用中的BeanDefinitions

3.loadBeanDefinitions(beanFactory)

该方法有4个实现,进入 org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)

	@Override
	protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
		// 给指定的beanFactory创建一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象
		// 3.1XmlBeanDefinitionReader的初始化
		XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
		// 将context加载了资源的environment配置给bean definition reader
		beanDefinitionReader.setEnvironment(this.getEnvironment());
		// 将 ResourceLoader换成 AbstractXmlApplicationContext 对象 AbstractXmlApplicationContext 实现了 ResourceLoader 接口
		beanDefinitionReader.setResourceLoader(this);
		beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
		// 提供给子类实现提供一些自定义的初始化策略
		initBeanDefinitionReader(beanDefinitionReader);
		//TODO 3.2加载beanDefinition操作
		loadBeanDefinitions(beanDefinitionReader);
	}

3.1 初始化一个XmlBeanDefinitionReader读取器对象,用于读取解析xml对象,并给该读取器设置一些属性

3.2 加载beanDefinitions

4.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) {
			//4.2加载解析beanDefinitions
			reader.loadBeanDefinitions(configLocations);
		}
	}

...

	@Override
	//4.2.1 从xml配置文件加载BeanDefinition对象
	public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
		Assert.notNull(locations, "Location array must not be null");
		int count = 0;
		// 如果有多个配置文件,循环读取加载,并统计总共加载了多少个BeanDefinition
		for (String location : locations) {
			//加载
			count += loadBeanDefinitions(location);
		}
		return count;
	}
...

@Override
	public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
		return loadBeanDefinitions(location, null);
	}

5.loadBeanDefinitions(location, null)

public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
		// 5.1获取上下文的资源加载器 AbstractXmlApplicationContext
		/**这里其实是获取 AbstractBeanDefinitionReader 的ResourceLoader,XmlBeanDefinitionReader继承bstractBeanDefinitionReader
		 * 在{@link org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(DefaultListableBeanFactory)}
		 * 中beanDefinitionReader.setResourceLoader(this) <>AbstractXmlApplicationContext</>;
		 * AbstractXmlApplicationContext的继承体系中有ResourcePatternResolver
		 */
		ResourceLoader resourceLoader = getResourceLoader();
		if (resourceLoader == null) {
			throw new BeanDefinitionStoreException(
					"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
		}
		// 5.2判断资源加载器是否 ResourcePatternResolver 类型(xml、url等不同类型统一接口为匹配类型)
		//ApplicationContext接口也有继承ResourcePatternResolver接口
		if (resourceLoader instanceof ResourcePatternResolver) {
			try {
				// 统一加载转换为Resource资源对象
				// 5.3通过路径获取 资源处理器 数组
				Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
				// 加载资源中配置的BeanDefinition对象,并返回数量
				/**@see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(org.springframework.core.io.Resource)
				 * 委派调用其子类XmlBeanDefinitionReader的方法,实现加载功能
				 * */
				//TODO 5.4通过 资源处理器 加载 BeanDefinitions
				int count = loadBeanDefinitions(resources);
				if (actualResources != null) {
					Collections.addAll(actualResources, resources);
				}
				if (logger.isTraceEnabled()) {
					logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
				}
				return count;
			}
		...
	}

...

public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
		Assert.notNull(resources, "Resource array must not be null");
		int count = 0;
		for (Resource resource : resources) {
			//5.4.1 调用的子类XmlBeanDefinitionReader方法
			count += loadBeanDefinitions(resource);
		}
		return count;
	}

...

@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		//5.4.2 将读取的xml资源进行编码处理
		return loadBeanDefinitions(new EncodedResource(resource));
	}

5.1 获取上下文的资源加载器 AbstractXmlApplicationContext

5.2 判断资源加载器是否 ResourcePatternResolver 类型(xml、url等不同类型统一接口为匹配类型)

5.3 统一加载转换为Resource资源对象

5.4 通过资源处理器 加载 BeanDefinitions

 6.loadBeanDefinitions(EncodedResource encodedResource)

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		...
		try {
			//1.首先调用EncodedResource#getResource去获取封装的资源resource,这里拿到的是classPathResource对象
			//然后在调用Resource#getInputStream获取一个inputStream
			InputStream inputStream = encodedResource.getResource().getInputStream();
			try {
				// 把xml文件流封装为InputSource对象
				InputSource inputSource = new InputSource(inputStream);
				//保存对应编码
				if (encodedResource.getEncoding() != null) {
					inputSource.setEncoding(encodedResource.getEncoding());
				}
				//TODO 2.do!执行加载逻辑
				return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
			}
			finally {
				inputStream.close();
			}
		}
		...
	}

6.1 首先调用EncodedResource#getResource去获取封装的资源resource,这里拿到的是classPathResource对象,然后在调用Resource#getInputStream获取一个inputStream,把inputStream文件流封装为InputSource对象

6.2 do!执行加载BeanDefinitions逻辑

7.doLoadBeanDefinitions()

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
		try {
			// 读取xml信息,将xml中信息保存到Document对象
			Document doc = doLoadDocument(inputSource, resource);
			//TODO 解析document对象,封装BeanDefinition对象并进行注册
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		...
	}


...

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//getRegistry()方法拿的是bean工厂对象,beanDefinition注册在工厂中
		//这个方法就是返回已经被注册在工厂中的beanDefinitions数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		// TODO 注册BeanDefinition
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		// 返回新注册的BeanDefinition数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

7.1 读取xml信息,将xml中信息保存到Document对象

7.2 解析document对象,封装BeanDefinition对象并进行注册

7.3 注册BeanDefinition

8.registerBeanDefinitions()

	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

...

protected void doRegisterBeanDefinitions(Element root) {
		BeanDefinitionParserDelegate parent = this.delegate;
		...
		//xml预处理,子类没有重写里面就是空实现
		preProcessXml(root);
		//TODO 解析xml
		parseBeanDefinitions(root, this.delegate);
		//xml后处理,子类没有重写里面就是空实现
		postProcessXml(root);

		this.delegate = parent;
	}

...

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//默认名称空间是"http://www.springframework.org/schema/beans"
		//进入条件
		if (delegate.isDefaultNamespace(root)) {
			//获取根元素下的子Node,注意,Node不一定是子标签,可能是回车,可能是注释
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					//拿到了<beans>下的子标签
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						//8.1 如果该标签属于beans的名称空间,则进入这个方法
						//xmlns="http://www.springframework.org/schema/beans"
						parseDefaultElement(ele, delegate);
					}
					else {
						//TODO 解析自定义标签元素
						//8.2 如果该标签属于其他的名称空间比如:context,aop等
						//xmlns:aop="http://www.springframework.org/schema/aop"
						//xmlns:context="http://www.springframework.org/schema/context"
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

8.1 解析bean标签

	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);
		}
		// 8.1.1 bean 元素处理(以该元素为例)
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		// 嵌套 beans 处理
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

8.1.1 bean 元素处理

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		// 解析bean元素为BeanDefinition,但是此时使用 BeanDefinitionHolder 又包装成了 BeanDefinitionHolder 对象
		//1 通过代理解析bean元素
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			/*
				 <bean id="demo" class="com.chenhao.spring.MyTestBean">
					 <property name="beanName" value="bean demo1"/>
					 <meta key="demo" value="demo"/>
					 <mybean:username="mybean"/>
				 </bean>
				 如果有自定义标签,则处理自定义标签
			 */
			//2 如果有要求的话渲染beanDefinition
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 完成BeanDefinition的注册
				//3 注册最终被渲染的实例到工厂中(进入该方法)
				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));
		}
	}

1.通过BeanDefinitionHolder代理解析bean元素

2.如果有要求的话渲染beanDefinition

3.注册最终被渲染的实例到工厂中

8.1.1.3 注册BeanDefinition

到此BeanDefinition已经完成了注册

	public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		/**@see org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition)*/
		// 1.注册bean definition的beanName 比如tk.mybatis.spring.mapper.MapperScannerConfigurer#0
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
		// Register aliases for bean name, if any.
		//2.为bean名称注册别名(如果有的话)。
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

...

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
...
		else {
			//这里面代表beanName还没有被注册
			//然后根据阶段不同又有一层判断
			if (hasBeanCreationStarted()) {
				//这个阶段是bean已经开始创建
				// 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
				// 仍然处于启动时的注册阶段
				// 所以这里走这个方法
				//beanDefinitionMap是工厂的一个属性,ConcurrentHashMap类型
				//他保存所有解析好的bean Definition的名称和实例的映射
				this.beanDefinitionMap.put(beanName, beanDefinition);
				//beanName也单独使用了一个ArrayList来保存,方便遍历
				this.beanDefinitionNames.add(beanName);
				//如果该bean definition是手动注册的,还要从manualSingletonNames中
				//移除bean definition的beanName,还要从manualSingletonNames中是LinkedHashSet
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

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

8.2 解析自定义标签

public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
		//拿到标签对应的名称空间URI
		//比如:http://www.springframework.org/schema/aop
		String namespaceUri = getNamespaceURI(ele);
		if (namespaceUri == null) {
			return null;
		}
		//TODO 8.2.1 拿到名称空间处理器解析器,去解析URI,获取名称空间处理器
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
		//8.2.2 通过处理器的某个解析器解析对应标签
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}

8.2.1 获取对应命名空间的处理器

public NamespaceHandler resolve(String namespaceUri) {
		//8.2.1.1 拿到处理器解析器中所有的处理器(进入该方法)
		//http://www.springframework.org/schema/aop --> org.springframework.aop.config.AopNamespaceHandler
		Map<String, Object> handlerMappings = getHandlerMappings();
		//拿到指定的处理器
		Object handlerOrClassName = handlerMappings.get(namespaceUri);
		//如果为null就返回null
		if (handlerOrClassName == null) {
			return null;
		}
		//如果是实例就返回实例
		else if (handlerOrClassName instanceof NamespaceHandler) {
			return (NamespaceHandler) handlerOrClassName;
		}
		else {
			//否则就一定是字符串
			String className = (String) handlerOrClassName;
			try {
				//通过加载器生成处理器的Class对象
				Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
				//必须要实现NamespaceHandler接口
				if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
					throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
							"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
				}
				//实例化一个
				NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
				//8.2.1.2 TODO 初始化,进入这个方法,里面初始化多个解析器
				namespaceHandler.init();
				//用实例覆盖原先handlerMappings中的字符串
				handlerMappings.put(namespaceUri, namespaceHandler);
				return namespaceHandler;
			}
		
	}
8.2.1.1 拿到处理器解析器中所有的处理器
private Map<String, Object> getHandlerMappings() {
		/**这里需要注意 如果idea的setting->degugger中关于toString的配置是勾选的话
		 * 在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}
		 * 中执行createReaderContext(resource)方法时会调用toString方法 从而给 handlerMappings 赋值
		 */
		Map<String, Object> handlerMappings = this.handlerMappings;
		if (handlerMappings == null) {
			synchronized (this) {
				handlerMappings = this.handlerMappings;
				if (handlerMappings == null) {
					if (logger.isTraceEnabled()) {
						logger.trace("Loading NamespaceHandler mappings from [" + this.handlerMappingsLocation + "]");
					}
					try {
						/** handlerMappingsLocation 数据来源
						 * 在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}初始化
						 * {@link XmlBeanDefinitionReader#createReaderContext(Resource)}
						 * {@link XmlBeanDefinitionReader#getNamespaceHandlerResolver()}
						 */
						Properties mappings = PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
						if (logger.isTraceEnabled()) {
							logger.trace("Loaded NamespaceHandler mappings: " + mappings);
						}
						handlerMappings = new ConcurrentHashMap<>(mappings.size());
						CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
						this.handlerMappings = handlerMappings;
					}
					catch (IOException ex) {
						throw new IllegalStateException(
								"Unable to load NamespaceHandler mappings from location [" + this.handlerMappingsLocation + "]", ex);
					}
				}
			}
		}
		return handlerMappings;
	}

1.这里需要注意 如果idea的setting->degugger中关于toString的配置是勾选的话在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)}中执行createReaderContext(resource)方法时会调用toString方法 从而给 handlerMappings 赋值。

2.handlerMappingsLocation 数据来源,调用链在{@link XmlBeanDefinitionReader#registerBeanDefinitions(Document, Resource)} >> {@link XmlBeanDefinitionReader#createReaderContext(Resource)} >>{@link XmlBeanDefinitionReader#getNamespaceHandlerResolver()}

8.2.1.2 初始化多个解析器 namespaceHandler.init()

该方法有多个实现,进入aop的实现AopNamespaceHandler

public void init() {
		//这里面每一个解析器都对应着AOP名称空间下的一个标签
		//不同的处理器注册的解析器都不一样
		//这里随便找一个解析器,查看他的注册流程(aspectj-autoproxy)8.2.2
		// In 2.0 XSD as well as in 2.1 XSD.
		registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
		registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
		registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());

		// Only in 2.0 XSD: moved to context namespace as of 2.1
		registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
	}

...

//aspectj-autoproxy 在8.2.2中会调用parse方法
class AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
		AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
		extendBeanDefinition(element, parserContext);
		return null;
	}

8.2.2 通过处理器的某个解析器解析对应标签

public BeanDefinition parse(Element element, ParserContext parserContext) {
		//将标签名称作为key,去处理器内部的parsers属性中,获取对应的value值,也就是解析器
		BeanDefinitionParser parser = findParserForElement(element, parserContext);
        //调用解析方法
		return (parser != null ? parser.parse(element, parserContext) : null);
	}


private BeanDefinitionParser findParserForElement(Element element, ParserContext parserContext) {
		//element存放了从xml中解析的信息(以aspectj-autoproxy为例)
		String localName = parserContext.getDelegate().getLocalName(element);
		/**parsers {@link org.springframework.aop.config.AopNamespaceHandler#init()}*/
		BeanDefinitionParser parser = this.parsers.get(localName);
		if (parser == null) {
			parserContext.getReaderContext().fatal(
					"Cannot locate BeanDefinitionParser for element [" + localName + "]", element);
		}
		return parser;
	}

1.根据传入的element获取对应的解析器,以aspectj-autoproxy为例

2.获取element中标签的名称,然后在根据名称去parser中获取对应解析器

3.调用解析方法parse,后面的步骤主要是注册BeanDefinition

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值