很多人表示,在说到Spring Ioc容器的加载过程的时候都不是很清楚,那么具体的加载过程到底是怎样的呢?一起通过下文来了解一下吧。
Spring Ioc容器加载流程
1、Resource定位-容器寻找数据的过程;
2、载入-将用户定义好的bean表示成IOC容器内部的数据结构,也就是BeanDefinition;
3、注册-将载入的BeanDefinition注册到IOC容器;
通过下面的图片内容再来详细的了解一下。
1、创建Ioc配置文件的抽象资源,这个抽象资源就包括了BeanDefinition的定义信息;
2、创建一个BeanFactory,这里使用DefaultListableBeanFactory;
3、创建一个载入BeanDefinition的读取器,这里使用XmlBeanDefinitionReader来载入XML文件形式的BeanDefinition,通过一个回调配置给BeanFactory;
4、从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成;
完成了整个载入以及注册Bean定义之后,需要的IOC容器就建立起来了,那么这个时候,就可以直接的使用IOC容器了;
bean.xml
容器启动入口
refresh()方法
载入BeanDefinition入口
定位resource
载入BeanDefinition的核心实现
向IOC容器注册
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException
{
super(parent);
this.setConfigLocations(configLocations);
if (refresh)
{
this.refresh();
}
} public void refresh() throws BeansException, IllegalStateException
{
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor)
{
this.prepareRefresh();
//这里在子类中启动refreshBeanFactory 的地方
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try
{
// 设置beanFactory的后置处理
this.postProcessBeanFactory(beanFactory);
//bean注册容器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册bean的后处理,在bean创建过程中调用
this.registerBeanPostProcessors(beanFactory);
//对上下文消息进行初始化
this.initMessageSource();
//初始化上线文的事件机制
this.initApplicationEventMulticaster();
//初始化其他的特殊的bean
this.onRefresh();
//检查监听bean,并向容器注册
this.registerListeners();
//实例化所有的(non-lazy-init)单件
this.finishBeanFactoryInitialization(beanFactory);
//发布容器时间,结束Refresh过程
this.finishRefresh();
}
catch (BeansException var9)
{
if (this.logger.isWarnEnabled())
{
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//为防止容器占用资源,在异常中销毁前面已经生成的单件bean
this.destroyBeans();
//重置‘active’标签
this.cancelRefresh(var9);
throw var9;
}
finally
{
this.resetCommonCaches();
}
}
} //创建 BeanFactory 并载入BeanDefinition
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
{
this.refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled())
{
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
protected final void refreshBeanFactory() throws BeansException
{
if (this.hasBeanFactory())
{
this.destroyBeans();
this.closeBeanFactory();
}
try
{
//创建beanFactory
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//载入bean入口
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor)
{
this.beanFactory = beanFactory;
}
}
catch (IOException var5)
{
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
} //AbstractXmlApplicationContext
// XmlBeanDefinitionReader 定位resource,XmlBeanDefinitionReader
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException
{
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
} //IOC 容器加载的核心方法
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException
{
try
{
InputStream inputStream = encodedResource.getResource()
.getInputStream();
try
{
//一:读取xml文件
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null)
{
inputSource.setEncoding(encodedResource.getEncoding());
}
//二:加载 beanefinition
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally
{
inputStream.close();
}
}
return var5;
}
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException
{
try
{
//一 1) 将xml文件转换为document
Document doc = this.doLoadDocument(inputSource, resource);
return this.registerBeanDefinitions(doc, resource);
}
}
//一 2) 开始执行
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
{
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
this.doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root)
{
this.preProcessXml(root);
//三 解析Element 获取xml内容
this.parseBeanDefinitions(root, this.delegate);
this.postProcessXml(root);
this.delegate = parent;
}
//解析Element 得到node 判断node内容
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)
{
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;
if (delegate.isDefaultNamespace(ele))
{
//读取document的内容
this.parseDefaultElement(ele, delegate);
}
else
{
delegate.parseCustomElement(ele);
}
}
}
}
else
{
delegate.parseCustomElement(root);
}
}
//四 判断xml中(document中节点的类型)
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)
{
if (delegate.nodeNameEquals(ele, "import"))
{
this.importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, "alias"))
{
this.processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, "bean"))
{
/* 五 载入beanDefinition 这里只是读取<bean>中的设置的class的name, 然后载入到BeanDefinition中,只是做个记录,并不设计对象的实例化,对象的实例化是在依赖注入时完成的*/
this.processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, "beans"))
{
this.doRegisterBeanDefinitions(ele);
}
}
//五 载入BeanDefinition 这里得到documentReader后,为具体的spring bean 解析准备了数据
protected void processBeanDefinition(Element ele, eanDefinitionParserDelegate delegate)
{
//具体处理了BeanDefinition交给 BeanDefinitionParserDelegate
/* 具体将<bean>的内容进行解析,解析为spring 的BeanDefinition
BeanDefinitionHolder是BeanDefinition对象的封装,封装了bean的名称和别
名,用他来完成 向IOC容器注册,得到的BeanDefinitionHolder是通过beanDefinitionParserDelegate 对 XML的元素的信息按照spring 的bean规则进行解析得到的*/
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null)
{
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try
{
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext()
.getRegistry());
}
catch (BeanDefinitionStoreException var5)
{
this.getReaderContext()
.error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
// BeanDefinition向IOC容器注册之后,发送消息
this.getReaderContext()
.fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
//载入BeanDefinition
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean)
{
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
List < String > aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr))
{
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty())
{
beanName = (String) aliases.remove(0);
if (this.logger.isDebugEnabled())
{
this.logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases");
}
}
if (containingBean == null)
{
this.checkNameUniqueness(beanName, aliases, ele);
}
//将xml的内置转换为spring的bean信息
AbstractBeanDefinition beanDefinition = this.parseBeanDefinitionElement(ele, beanName, containingBean);
}
//对<bean>的内容进行解析,转换为spring的bean
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean)
{
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute("class"))
{
className = ele.getAttribute("class")
.trim();
}
String parent = null;
if (ele.hasAttribute("parent"))
{
parent = ele.getAttribute("parent");
}
try
{
//生成需要的BeanDefinition对象,为BeanDefinition的载入做准备
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
//设置<bean>的attribute scope,init,destory 等
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//设置元数据 如 key ,value这样的
this.parseMetaElements(ele, bd);
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
this.parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析<bean>构造函数
this.parseConstructorArgElements(ele, bd);
//设置<bean>property元素
this.parsePropertyElements(ele, bd);
this.parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(this.extractSource(ele));
AbstractBeanDefinition var7 = bd;
return var7;
}
}
finally
{
this.parseState.pop();
}
return null;
} /注册 BeanDefinition
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException
{
//获取bean的 名称
String beanName = definitionHolder.getBeanName();
//注册bean 并将bean放入到ioc容器里面
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null)
{
String[] var4 = aliases;
int var5 = aliases.length;
for (int var6 = 0; var6 < var5; ++var6)
{
String alias = var4[var6];
//注册其他信息 是否是单例,是否允许重载 是否是abstract 类
registry.registerAlias(beanName, alias);
}
}
}
//DefaultListableBeanFactory 具体执行注册的
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 var9)
{
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Validation of bean definition failed", var9);
}
}
//bean 已经存在
BeanDefinition existingDefinition = (BeanDefinition) this.beanDefinitionMap.get(beanName);
if (existingDefinition != null)
{
//不允许覆盖 报异常
if (!this.isAllowBeanDefinitionOverriding())
{
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + existingDefinition + "] bound.");
}
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else
{
if (this.hasBeanCreationStarted())
{
Map var4 = this.beanDefinitionMap;
//synchronized,保证数据一致性
synchronized(this.beanDefinitionMap)
{
//将bean放入容器
this.beanDefinitionMap.put(beanName, beanDefinition);
List < String > updatedDefinitions = new ArrayList(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName))
{
Set < String > updatedSingletons = new LinkedHashSet(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else
{
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || this.containsSingleton(beanName))
{
this.resetBeanDefinition(beanName);
}
} Spring Ioc容器的加载流程你都了解了吗?更多和Spring Ioc容器相关的常见问题,可以继续关注奇Q工具网来了解哦。
推荐阅读: