spring初始化refresh()方法中obtainFreshBeanFactory()源码走读。
来源:互联网 发布:mysql 5.5.21.tar.gz 编辑:程序博客网 时间:2024/06/16 14:44
简述obtainFreshBeanFactory()方法:
分析ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();方法
描述:该方法主要是解析我们项目配置的 application.xml、xxx.xml 定义的import、bean、resource、profile、、、、、。
这里我们就简单的分析下解析XML
1、解析<bean id="" classs="" 、、、、/>将element属性赋值到对应的AbstractBeanDefinition 定义的对象中
2、将AbstractBeanDefinition继续赋值给一个BeanDefinitionHolder(包含aliases、beanName、beanDefinition(就是我们AbstractBeanDefinition))
3、或取BeanDefinitionHolder对象的beanName和beanDefinition 将其注册到BeanDefinitionRegistry对象中(其实里面就是将beanName 添加到List<String>
,将beanName--key和beanDefinition--value 保存到 Map<String, BeanDefinition> 中。)
目标:其实这个方法的核心就是解析XML 或扫描注解 将其属性封装到BeanDefinition 对象中,并对它beanName(key) BeanDefinition(v) 保存到一个Map 中,这个obtainFreshBeanFactory()的工作
就完成了,这就保证了后面spring加载依赖注入提供了对应的元数据。
=========================开始=================================
类:org.springframework.context.support.AbstractApplicationContext
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//prepareRefresh()方法调用链路--->initPropertySources();
// ---->AbstractRefreshableWebApplicationContext.initPropertySources()
// --->StandardServletEnvironment.initPropertySources()
// 主要作用就是通过StandardServletEnvironment类 获取到web.xml中<context-param>--xxx/applicationContext.xml 的参数信息
//启动打印日志 DEBUG o.s.w.c.s.StandardServletEnvironment - Initialized StandardServletEnvironment with PropertySources [serv // letConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment]
prepareRefresh();// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
描述:该方法主要是解析我们项目配置的 application.xml、xxx.xml 定义的import、bean、resource、profile、、、、、。
这里我们就简单的分析下解析XML
1、解析<bean id="" classs="" 、、、、/>将element属性赋值到对应的AbstractBeanDefinition 定义的对象中
2、将AbstractBeanDefinition继续赋值给一个BeanDefinitionHolder(包含aliases、beanName、beanDefinition(就是我们AbstractBeanDefinition))
3、或取BeanDefinitionHolder对象的beanName和beanDefinition 将其注册到BeanDefinitionRegistry对象中(其实里面就是将beanName 添加到List<String>
,将beanName--key和beanDefinition--value 保存到 Map<String, BeanDefinition> 中。)
目标:其实这个方法的核心就是解析XML 或扫描注解 将其属性封装到BeanDefinition 对象中,并对它beanName(key) BeanDefinition(v) 保存到一个Map 中,这个obtainFreshBeanFactory()的工作
就完成了,这就保证了后面spring加载依赖注入提供了对应的元数据。
/**----》进入org.springframework.context.support.AbstractRefreshableApplicationContext--refreshBeanFactory()方法
* Tell the subclass to refresh the internal bean factory.
* @return the fresh BeanFactory instance
* @see #refreshBeanFactory()
* @see #getBeanFactory()
*/
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();----》点击进入
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
继承关系图
/*** This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
//检查BeanFactory是否已经存在,存在的话销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}try {
DefaultListableBeanFactory beanFactory = createBeanFactory();//实例化DefaultListableBeanFactory
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory); //解析XML 装载成BeanDefinition对象 --》点击进入
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}===============================================================================org.springframework.web.context.support.AbstractRefreshableApplicationContext.loadBeanDefinitions()方法 ---(抽象类AbstractRefreshableApplicationContext 分别被下面四个 类 实现
--》进入org.springframework.web.context.support.XmlWebApplicationContext--loadBeanDefinitions()方法/**
* 通过XmlBeanDefinitionReader 加载和定义bean
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(getEnvironment()); //设置 StandardEnvironment
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);//解析spring配置的XXXXapplication.xml 具体执行-AbstractBeanDefinitionReader.loadBeanDefinitions()}
loadBeanDefinitions(beanDefinitionReader);XmlWebApplicationContext
执行:org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions()方法目的:将spring xxxxApplication.xml--转化为Resource 可以理解为IO流资源下面的 resourceLoader 就是 XmlWebApplicationContext上一步方法赋值的 XmlWebApplicationContextpublic int loadBeanDefinitions(String location, Set<Resource> actualResources) throws BeanDefinitionStoreException {ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot import bean definitions from location [" + location + "]: no ResourceLoader available");
}
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
int loadCount = loadBeanDefinitions(resources); //进入--这里以XML解析为例
if (actualResources != null) {
for (Resource resource : resources) {
actualResources.add(resource);
}
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location pattern [" + location + "]");
}
return loadCount;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
int loadCount = loadBeanDefinitions(resource);
if (actualResources != null) {
actualResources.add(resource);
}
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
}
return loadCount;
}
}---》进入后 org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions()方法;主要作用 Resource--》EncodedResource(实现InputStreamSource)---》InputSource IO流public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isInfoEnabled()) {
logger.info("Loading XML bean definitions from " + encodedResource.getResource());
}
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<EncodedResource>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());//上面的这条语句进入之后构造出 org.w3c.dom.Document doc = doLoadDocument(inputSource, resource);
//之后的工作就是利用java api提供的Document解析XML}
finally {
inputStream.close();
}
}
//各种不断进入之后
org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement()方法private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
/**解析import 标签的XML 例如:
* <import resource="applicationContext-common.xml" />
* <import resource="applicationContext-datasource.xml" />
* 进入importBeanDefinitionResource()--因为每个import引入一个xml spring 还是会向现在我们解析application.x *ml去解析一样--里面调用的方法
* int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
* 执行的是org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions *( locatiom, actualResources)方法
*
**/
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate); //解析bean<bean id="" class="" /> --进入
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}----》查看解析进入bean的具体实现方法 org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition()方法解析:BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);1、对Element 属性getAttribute("id"/"name")2、对获得id/name 赋值给GenericBeanDefinition对象 它实现AbstractBeanDefinition-->BeanDefinition接口(AbstractBeanDefinition对象就是保存解析的bean 属性 并对默认属性赋值 id/name/scope/lazyInit/beanClass/initMethodName/propertyValues......)方法:AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, conta iningBean);3、构造返回 new BeanDefinitionHolder(beanDefinition,beanName,aliasesArray) 里面就是beanName、aliasesArray、beanDefinition(对象) 方便后面spring 依赖注入直接通过beanName/aliasesArray(别名) 获取beanDefinition对象。
解析:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()1、获取bdHolder的beanName和BeanDefinition 对象2、将BeanDefinitionRegistry----》registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());3、将beanName 添加到List<String>,将beanName--key和beanDefinition--value 保存到 Map<String, BeanDefinition> 中。
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
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));
}
}
2 0
- spring初始化refresh()方法中obtainFreshBeanFactory()源码走读。
- Spring源码解析之零 ------ 容器初始化过程(refresh()方法)概要
- Spring源码阅读--AbstractApplicationContext refresh()方法调用
- JFinal源码走读_1_jfinal初始化
- JFinal源码走读_3_ActiveRecord初始化
- 源码解读(二): spring容器初始化的refresh操作
- Twemproxy源码走读(3):初始化流程
- spring 容器的refresh方法
- 浅析Spring IoC源码(十一)Spring refresh()方法解析之一
- 浅析Spring IoC源码(十一)Spring refresh()方法解析后记2
- Spring ioc容器启动流程—obtainFreshBeanFactory
- Spring源码由浅入深系列三 refresh
- 浅析Spring IoC源码(三)分析refresh()方法前的准备篇(一)
- Spring中bean初始化时机初始化方法和销毁方法
- 做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析之一
- 做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记1
- 做一个合格的程序猿之浅析Spring IoC源码(十一)Spring refresh()方法解析后记2
- Spring的refresh()方法相关异常
- couchbase 3.0.1 问题总结
- 2015总结
- 蓝桥--在线评测--入门训练
- csr8670--sink工程的大致工作流程分析(以speaker为例)一
- 扩大栈空间
- spring初始化refresh()方法中obtainFreshBeanFactory()源码走读。
- LeetCode_OJ【44】Wildcard Matching
- Android:RelativeLayout 属性
- 不兼容结构的协调——适配器模式(二):算法库适配器模式解决方案
- Tomcat 启动报错:host-manager does not exist or is not a readable directory
- 干掉头疼的finished with non-zero exit value 2
- Docker网络详解及pipework源码解读与实践
- 【matconvnet】故障排除:Error using mex nvcc fatal : Unsupported gpu architecture 'compute_52'
- UIView常见属性方法