至于为什么要从老书开始,虽然有些不妥,但也有点随意的成分在,旁边有什么书就从那本开始了。XmlBeanFactory 其实已经被spring3.1开始废弃了,但是还是有东西可以学习的。之后如果博主的能力有提高,会去将最新版的核心代码整理一篇出来,与之前的做下比较。
以下基本是对源码的分析
先给老哥们上一张图,很复杂,各种继承实现。
以下两点明确下:
/** Map from alias to canonical name. */
// 提供了map作为 别名的缓存
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
继承的好处就是向上造型,并且java不支持多继承,所以为了最底层的DefaultListableBeanFactory拥有全面的功能,需要父类就开始继承,以便拥有所有相关接口的默认实现
XmlBeanFactory bf = new XmlBeanFactory(new ClassPatchResource("test.xml"));
// 会调用到 XmlBeanFactory里面的一个构造器
public XmlBeanFactory(Resource resource) throws BeansException {
// 再调用另一个构造器
this(resource, null);
}
// 类里面的 reader对象,
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
super(parentBeanFactory);
// 使用类里面对reader对象对loadBeanDefinitions(加载Bean方法,根据资源)
this.reader.loadBeanDefinitions(resource);
}
传入资源的时候会将资源传递给 XmlBeanDefinitionReader 去加载资源,再进入loadBeanDefinitions
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 传入 EncodedResource 对象是想判断是否有 编码 的要求
return loadBeanDefinitions(new EncodedResource(resource));
}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
// 断言 encodedResource 不能为 null
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}
// resourcesCurrentlyBeingLoaded 是一个 ThreadLocal对象,得到的是本线程的资源
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
// 没有则创建
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// 得到resource里面的inputStream流
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 构造InputSource。 A single input source for an XML entity.
InputSource inputSource = new InputSource(inputStream);
// 如果存在编码要求,则会对inputSource进行设置。
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 传入inputSource (含有 resource 的输入流(inputStream)) 和 封装在encodedResource中的resource
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}
上面做了一些准备工作,对resource资源的封装。
doLoadBeanDefinitions 才是去做加载工作
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 验证xml文件流的格式,并转换成 document 对象
Document doc = doLoadDocument(inputSource, resource);
// 解析并注册 beanDefinition
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
} catch(Exception e) {
// 省略捕捉的异常
...
}
}
// 根据得到xml文件解析成 Document 对象
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
// inputSource: xml文件的输入流
// getEntityResolver: 判断xml文件需要 dtd 还是 xsd 验证文件的获取方式
// errorHandler: 错误日志一类
// getValidationModeForResource 获取 dtd 或者 xsd 的验证模型
// isNamespaceAware:XML解析器是否应该支持XML命名空间
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware());
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 创建默认的documentReader,DefaultBeanDefinitionDocumentReader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// 得到现有的beanDefinition个数
int countBefore = getRegistry().getBeanDefinitionCount();
// 将解析doc对象的工作委派给documentReader来完成,这里默认的是DefaultBeanDefinitionDocumentReader 类
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
// 解析并注册 beanDefinition
doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent);
// profile 解析,这里的profile是指环境设置,类似dev、pro,开发环境和生产环境
if (this.delegate.isDefaultNamespace(root)) {
// 在root节点得到 profile 属性
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
// 对环境参数设置 profile参数
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isDebugEnabled()) {
logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
// 设计模式中的模版方法 ,hook 钩子
preProcessXml(root);
// 解析xml中的节点
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);
this.delegate = parent;
}
// 解析xml中的节点
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)) {
parseDefaultElement(ele, delegate);
}
// 不是,使用自定义解析
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
// 解析默认命名空间,元素的类型
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
// 默认解析 4种ele
// import
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
// alias
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
// bean
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
// beans,递归调用解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}