您的位置:首页 > 编程语言 > Java开发

Spring -- 源码分析 -- XmlBeanFactory(。。。未完待续)

2019-06-18 14:50 274 查看

1、读取 xml,生成 dom 树

1、继承 DefaultListableBeanFactory,该类是 BeanFactory 容器的最终载体;使用 XmlBeanDefinitionReader 来加载xml

[code]//XmlBeanFactory.java   77行
public class XmlBeanFactory extends DefaultListableBeanFactory {
this.reader.loadBeanDefinitions(resource);
}

2、将 resource 资源,封装成 sax 需要的类型 InputSource 

[code]//XmlBeanDefinitionReader.java   332行
InputSource inputSource = new InputSource(inputStream);
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());

3、使用 sax 将资源转换为一棵 dom 树

[code]//XmlBeanDefinitionReader.java   391行
Document doc = doLoadDocument(inputSource, resource);

4、dom 解析原理

[code]//1.构造工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//2.注入命名空间,也就是在节点对象中显示命名空间
factory.setNamespaceAware(true);
//3.开启验证
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
//4.验证文件 xsd 和 dtd 的路径解析器
builder.setEntityResolver(new ResourceEntityResolver(new DefaultResourceLoader()));
builder.setErrorHandler(null);

//5.转化为 sax 需要的资源类型
InputSource source = new InputSource(new ClassPathResource("application-test.xml").getInputStream());
Document document = builder.parse(source);
Element root = document.getDocumentElement();
System.out.println(root.getNamespaceURI());
NodeList list = root.getChildNodes();
for (int i = 0; i < list.getLength(); i++) {
Node node = list.item(i);
if (node instanceof Element) {
Element element = (Element) node;
System.out.println(element.getAttribute("class"));
System.out.println(element.getNamespaceURI());
}
}

2、根据 dom 树节点解析 bean

1、使用 DefaultBeanDefinitionDocumentReader 来解析 dom 树

[code]//XmlBeanDefinitionReader.java   508行
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));

//DefaultBeanDefinitionDocumentReader    93行
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);

2、DefaultBeanDefinitionDocumentReader 委托 BeanDefinitionParserDelegate 解析节点

[code]//DefaultBeanDefinitionDocumentReader.java   145行
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(this.readerContext, root, parent);

//子类扩展1
preProcessXml(root);
//解析
parseBeanDefinitions(root, this.delegate);
//子类扩展2
postProcessXml(root);

3、根据命名空间使用默认或自定义解析

[code]//DefaultBeanDefinitionDocumentReader.java   168行
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}else {
delegate.parseCustomElement(ele);
}

4、解析默认命名空间标签,import、alias、bean、beans 标签

[code]//DefaultBeanDefinitionDocumentReader.java   182行
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
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);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}

5、解析 bean 标签,注册到容器中

[code]//DefaultBeanDefinitionDocumentReader.java   305行
//1.开始解析标签
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
//2.如果存在非默认标签, 继续解析
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
//3.注册bean
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

6、解析准备

[code]//BeanDefinitionParserDelegate.java   437行
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//...省略, 这部分是在解析别名
//真正的解析过程
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
//...省略, 这部分是在为 bean 寻找名称
//返回 BeanDefinitionHolder 对象
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);

7、解析过程

[code]//BeanDefinitionParserDelegate.java   537行
AbstractBeanDefinition bd = createBeanDefinition(className, parent);

//1.解析标签上属性, 如scope、abstract、lazy-init、depends-on、primary、init-method、destroy-method、factory-method、factory-bean
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

//2.解析 meta 元数据, 并不作为 bean 的属性存在, 但是可以从 bean 中获取
parseMetaElements(ele, bd);

//3.标记覆盖方法
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

//4.解析 constructor-arg 构造器属性
parseConstructorArgElements(ele, bd);

//5.解析 property 内部标签
parsePropertyElements(ele, bd);

//6.解析 qualifier 内部标签
parseQualifierElements(ele, bd)

3、注册 Bean

1、注册 bean,并注册别名

[code]//DefaultBeanDefinitionDocumentReader.java   311行
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

//BeanDefinitionReaderUtils.java   142行
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {

//1.注册bean
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

//2.注册别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}

4、获取 Bean 过程

1、根据名称获取实例 bean

[code]ApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-test.xml");
BeanTest bean = (BeanTest) context.getBean("beanTest");

2、最终调用的是  AbstractBeanFactory 的 doGetBean 方法

[code]//AbstractBeanFactory.java    231行
//1.获取真正的 beanName, 主要是针对别名
final String beanName = transformedBeanName(name);
//2.获取缓存的实例 bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//3.实例化的 bean 不一定是最终需要的, 可能是工厂类, 这里需要使用工厂策略进行判断
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
//4.当前BeanFactory没有该bean, 去父类BeanFactory查找
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
return (T) parentBeanFactory.getBean(nameToLookup, args);
}

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//5.实例化依赖
String[] dependsOn = mbd.getDependsOn();
for(;;;){
registerDependentBean(dependsOnBean, beanName);
getBean(dependsOnBean);
}

if (mbd.isSingleton()) {
//6.真正实例化bean的地方,使用的是工厂策略方法
sharedInstance = getSingleton(beanName, new ObjectFactory<>(){...});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

//7.实例化出来的 bean 不一定是想要的类型, 使用转换器进行转换
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
return getTypeConverter().convertIfNecessary(bean, requiredType);
}

return (T) bean;
}

2、获取缓存bean,该方法中出现了很多集合,理解起来有些困难,基本上是为了解决循环依赖而出现的

[code]//DefaultSingletonBeanRegistry.java    183行
Object singletonObject = this.singletonObjects.get(beanName);
//...省略

3、实例化过程

[code]//AbstractAutowireCapableBeanFactory.java    445行
//1.根据类名,调用无参构造器进行初始化
resolveBeanClass(mbd, beanName);
//2.标记覆盖方法
mbd.prepareMethodOverrides();
//3.在 bean 初始化之前,调用 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation,这里可以控制 bean 的生成,如果这里返回的 bean 不为null,那么后续的初始化不会调用,直接调用 postProcessAfterInitialization
Object bean = resolveBeforeInstantiation(beanName, mbd);
//4.真正实例化bean
Object beanInstance = doCreateBean(beanName, mbd, args);

4、doCreateBean 方法(最复杂)

[code]//AbstractAutowireCapableBeanFactory.java    504行
BeanWrapper instanceWrapper = null;

。。。未完待续

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: