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(包含aliasesbeanNamebeanDefinition(就是我们AbstractBeanDefinition
3、或取BeanDefinitionHolder对象的beanNamebeanDefinition 将其注册到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.
      //创建BeanFactory,如果已有就销毁,没有就创建。此类实现了对BeanDefinition的装载
  
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();
}
}
}

----》分析ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();方法
描述:该方法主要是解析我们项目配置的 application.xml、xxx.xml 定义的import、bean、resource、profile、、、、、。
这里我们就简单的分析下解析XML
1、解析<bean id="" classs="" 、、、、/>将element属性赋值到对应的AbstractBeanDefinition 定义的对象中
2、将AbstractBeanDefinition继续赋值给一个BeanDefinitionHolder(包含aliasesbeanNamebeanDefinition(就是我们AbstractBeanDefinition
3、或取BeanDefinitionHolder对象的beanNamebeanDefinition 将其注册到BeanDefinitionRegistry对象中(其实里面就是将beanName 添加到List<String>
,将beanName--key和beanDefinition--value 保存到 Map<String, BeanDefinition> 中。
目标:其实这个方法的核心就是解析XML 或扫描注解  将其属性封装到BeanDefinition 对象中,并对它beanName(key) BeanDefinition(v) 保存到一个Map 中,这个obtainFreshBeanFactory()的工作
就完成了,这就保证了后面spring加载依赖注入提供了对应的元数据。
/**
* 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;
}
----》进入org.springframework.context.support.AbstractRefreshableApplicationContext--refreshBeanFactory()方法
继承关系图

/**
* 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上一步方法赋值的 XmlWebApplicationContext 

public 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
原创粉丝点击