提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
对Spring IOC主流程中Bean定义解析注册流程分支的总结
这个分支的主要工作内容有两个
1 将xml中的配置信息解析成bean定义信息(BeannDefinition)对象
2 将BeanDefinition对象注册到工厂中,为后续实例化bean对象做准备
public abstract class AbstractXmlApplicationContext extends AbstractRefreshableConfigApplicationContext {
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(this.getEnvironment());
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);
loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
//容器初始化时设置了这个参数 他是xml配置文件的路径
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
}
在继续跟方法之前,先介绍下DefinitionReader家族,防止后边跟晕了
一、DefinitionReader家族以及分工
DefinitionReader是家族的顶级接口,方法定义中可以看出主要就是用来加载bean定义信息的。其中loadBeanDefinitions有四个重载方法。画红框的三个重载方法统一由AbstractBeanDefinitionReader做了实现,唯一的一个框外的loadBeanDefinitions方法由其三个子类分别实现。
AbstractBeanDefinitionReader的主要目的就是将入参的字符串统一转化为Resource对象,便于子类处理。
1.1 继续跟踪代码reader.loadBeanDefinitions()
了解了BeafinitionReader家族的使命,接着跟踪加载方法。会跟踪到AbstractBeanDefinitionReader类中
public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
//实现顶级接口中loadBeanDefinitions的方法之一
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}
//实现顶级接口中loadBeanDefinitions的方法之二
@Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
}
//这个方法完成了AbstractBeanDefinitionReader的主要使命,就是将入参统一成Resource对象
public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
//获取资源加载器 其实就是容器
ResourceLoader resourceLoader = getResourceLoader();
。。省略代码
if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
//通过资源解析器获取资源
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
//执行加载bean定义
int count = loadBeanDefinitions(resources);
。。省略代码
return count;
}
catch (IOException ex) {
。。省略代码
}
}
else {
// Can only load single resources by absolute URL.
Resource resource = resourceLoader.getResource(location);
//执行加载bean定义
int count = loadBeanDefinitions(resource);
。。省略代码
return count;
}
}
//实现顶级接口中loadBeanDefinitions的方法之三
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
//最后交给子类来实现
count += loadBeanDefinitions(resource);
}
return count;
}
}
1.2 继续跟踪代码reader.loadBeanDefinitions()
继续跟踪会跟踪到具体的子类XmlBeanDefinitionReader中
public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
//实现顶级接口中loadBeanDefinitions的方法之四
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
}
//加载处理
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
。。。省略代码
try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
InputSource inputSource = new InputSource(inputStream);
。。。省略代码
//真正的执行加载
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
catch (IOException ex) {
。。。省略代码
}
finally {
。。。省略代码
}
}
//真正加载处理
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//将资源加载成Document对象 到这里加载结束了 剩下的是注册环节
Document doc = doLoadDocument(inputSource, resource);
//执行注册
int count = registerBeanDefinitions(doc, resource);
。。。省略代码
return count;
}
。。。省略代码
}
//注册bean定义信息
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
//委托给BeanDefinitionDocumentReader类完成后续的注册流程
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
}
二、BeanDefinitionDocumentReader
继续跟踪documentReader.registerBeanDefinitions方法,会从BeanDefinitionReader家族来到BeanDefinitionDocumentReader家族。虽然名字很像但是他们没有血缘关系
这个家族的使命就是注册bean,并且只有DefaultBeanDefinitionDocumentReader一个实现类
public class DefaultBeanDefinitionDocumentReader implements BeanDefinitionDocumentReader {
//注册bean定义
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
//真正执行bean定义注册
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
。。。省略注释
BeanDefinitionParserDelegate parent = this.delegate;
//委托给BeanDefinitionParserDelegate来执行解析
this.delegate = createDelegate(getReaderContext(), root, parent);
。。。省略代码
preProcessXml(root);
//解析bean定义信息 在这里
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
//解析的目的是将Element元素解析成BeanDefinition对象最终注入到工厂中
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)) {
//解析默认标签(bean标签在这里 所以继续跟这个方法)
parseDefaultElement(ele, delegate);
}
else {
//解析自定义标签(aop mvc 都是自定义标签) 后续总结aop时在跟这里
delegate.parseCustomElement(ele);
}
}
}
}
else {
//解析自定义标签(aop mvc 都是自定义标签) 后续总结aop时在跟这里
delegate.parseCustomElement(root);
}
}
//解析默认标签
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//这里完成了解析 BeanDefinitionHolder内部封装了bean定义信息
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//将bean定义信息注册到工作
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
这个类是解析注册流程中最后的一个委托了,最后在大致跟以下delegate.parseBeanDefinitionElement(ele)方法
public class BeanDefinitionParserDelegate {
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
//继续跟这里
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//解析出标签中的id
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析出标签中的name
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//默认bean名称是id
String beanName = id;
//如果没定义id 但是有name 那么就用name
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isTraceEnabled()) {
logger.trace("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
。。。省略代码
//获取bean定义
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
。。。省略代码
String[] aliasesArray = StringUtils.toStringArray(aliases);
//将bean定义信息封装到BeanDefinitionHolder对象中
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//获取类全路径名称
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
//看看有没有父标签
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//这里创建了一个bean定义对象
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//解析流程继续跟这里
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
...省略代码
return bd;
}
...省略代码
}
//最终的解析流程
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
//解析作用域 scope
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
// Take default from containing bean in case of an inner bean definition.
bd.setScope(containingBean.getScope());
}
//解析是否是抽象的
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
//解析是否懒加载
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (isDefaultValue(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
...后边还有很多 可以自己看源码
return bd;
}
}
总结
1 容器将解析和加载bean定义信息的任务委托给了BeanDefinitionReader来处理
2 BeanDefinitionReader的子类AbstractBeanDefinitionReader将加载的入参从字符串统一封装成了Resource对象交给子类继续处理
3 其中的一个子类XMLBeanDefinitionReader将Resource封装成了Document对象并委托BeanDefinitionDocumentReader完成后续的解析和注册
4 BeanDefinitionDocumentReader的唯一实现类DefaultBeanDefinitionDocumentReader委托BeanDefinitionParserDelegate将Document对象解析成BeanDefinition对象最终将其注册到BeanFactory工厂中