05document转为BeanDefinition并注册过程

接着之前的文章4继续分析,文章4里的步骤三的C_3里调用xmlReader(XmlBeanDefinitionReader)的
doLoadBeanDefinitions(InputSource inputSource, Resource resource)方法,该方法最后一行进入
registerBeanDefinitions(doc, resource)方法里,该方法最终调用他的好友
documentReader.registerBeanDefinitions(doc, createReaderContext(resource))方法

Ⅰ、代码流程

一、程序入口位于documentReader的registerBeanDefinitions方法
//DefaultBeanDefinitionDocumentReader.registerBeanDefinitions
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();//获得docuemnt的根元素
doRegisterBeanDefinitions(root);
}
protected void doRegisterBeanDefinitions(Element root) {
//1、检查根节点的profile属性
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
//this.environment就是beanFactory的environment即StandardEnvironment
Assert.state(this.environment != null, "Environment must be set for evaluating profiles");
//解析得到比如dev,uat这样的数组
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
//让environment去判断spring.profiles.active或SPRING_PROFILES_ACTIVE的值是否包含dev(uat),
//包含说明当前整个xml是active的,可以继续,否则直接return
if (!this.environment.acceptsProfiles(specifiedProfiles)) {
return;
}
}
//2、创建委托对象,交给委托对象解析<beans>标签
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one.
BeanDefinitionParserDelegate parent = this.delegate;//表面上看该属性为空,但是当
//<beans>里面嵌套有<beans>时会引起递归调用当前方法,此时该属性不为空,该对象
//表示上次解析<beans>时的委托对象,每一个delegate对象对应一个<beans>标签,
//当存在内外嵌套<beans>场景时,内层的部分属性继承外层的,所以递归到内层
//<beans>时要拿到外层的delegate对象做相关处理
this.delegate = createDelegate(this.readerContext, root, parent);//就是BeanDefinitionParserDelegate
preProcessXml(root);//模板空方法,允许开发者覆盖之后,实现在解析document之前先解析xml里的自定义标签
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);//同preProcessXml,也是空方法,实现扩展功能用
this.delegate = parent;
}
protected BeanDefinitionParserDelegate createDelegate(
XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
//这句createHelper方法创建了个寂寞
BeanDefinitionParserDelegate delegate = createHelper(readerContext, root, parentDelegate);
if (delegate == null) {
delegate = new BeanDefinitionParserDelegate(readerContext, this.environment);
delegate.initDefaults(root, parentDelegate);
}
return delegate;
}
@Deprecated
protected BeanDefinitionParserDelegate createHelper(
XmlReaderContext readerContext, Element root, BeanDefinitionParserDelegate parentDelegate) {
return null;
}
二、documentReader开始解析root节点
delegate作为documentReader的助手角色参与其中
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//如果是默认命名空间
if (delegate.isDefaultNamespace(root)) {//正常进入该分支
NodeList nl = root.getChildNodes();
//遍历<beans>下的所有节点
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);
}
}
//delegate.isDefaultNamespace
public boolean isDefaultNamespace(Node node) {
return isDefaultNamespace(getNamespaceURI(node));
}
//delegate.getNamespaceURI
public String getNamespaceURI(Node node) {
return node.getNamespaceURI();//比如当前是<beans>则返回http://www.springframework.org/schema/beans
}
//delegate.isDefaultNamespace
public boolean isDefaultNamespace(String namespaceUri) {
return (!StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri));
//内部有个常量public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans";
}
三、documentReader开始解析root下的子节点,比如<bean>、<import>、<alise>、<beans>
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);//这里就会递归到上面步骤一的doRegisterBeanDefinitions方法里
}
}
protected void importBeanDefinitionResource(Element ele) {
//1、解析import标签的resource属性得到被引入xml的路径字符串
String location = ele.getAttribute(RESOURCE_ATTRIBUTE);
//2、利用environment把带有占位符的路径字符串变成真正的路径字符串
location = environment.resolveRequiredPlaceholders(location);
//3、借助之前的xmlReader去再次解析xml
//context类似threadLocal用法,该上下文里的reader就是xmlReader,等于
//程序执行流程又回到了文章4的步骤6的第三个loadBeanDefinitions方法。
int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);
//4、发出事件,触发关心者去处理import事件,暂时不考虑那么细,略
getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));
}
//暂时略
protected void processAliasRegistration(Element ele) {
}
四、documentReader开始解析<bean>节点,交给助手delegate去做
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//1、交给delegate去解析<bean>节点,注意这里得到的是holder对象
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//2、判断如果有自定义属性调用自定义处理器装饰下bdHolder对象
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
//decorateBeanDefinitionIfRequired方法里判断如果当前<bean>存在自定义
//属性,则调用NamespaceHandlerResolver对象根据自定义属性的命名空间得到
//NamespaceHandler命名空间处理器,用该处理器解析属性得到被装饰后的
//holder对象(就是上面bdHolder,等于这里调用开发者的处理器把bdHolder进行处理了)
//该方法代码见附录1
try {
//3、注册bdHolder到beanFactory里,getReaderContext().getRegistry()是beanFactory,最终修改如下内存,到此doc变为BeanDefinition对象流程结束。
beanFactory
bd属性
|-beanDefinitionMap 类型Map<String, BeanDefinition>,key是beanName,value是bd对象
|-beanDefinitionNames 类型List<String>,元素是beanName
// 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));
}
}
五、delegate开始解析<bean>标签
//delegate.parseBeanDefinitionElement(ele)
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
//delegate.parseBeanDefinitionElement(ele, containingBean)
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//1、解析id和name属性
String id = ele.getAttribute(ID_ATTRIBUTE);
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//2、判断name属性如果带逗号说明是别名,分割后加入别名list
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//3、如果id为空并且别名list不为空时,取第一个别名作为beanName
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0);
if (logger.isDebugEnabled()) {
logger.debug("No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases");
}
}
//4、检查beanName必须唯一,不唯一就报错
if (containingBean == null) {//正常进入该分支
checkNameUniqueness(beanName, aliases, ele);//通过usedNames检查beanName是否唯一
}
//5、得到Definition对象
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {//正常不会进入该分支,如果xml里去掉id="person"则进入这里
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);//DefaultBeanNameGenerator.generateBeanName-->BeanDefinitionReaderUtils.generateBeanName内部规则为class完全限定名learn.dto.Person+#+序号,这里是learn.dto.Person#0
//为了向后兼容,用完全限定名作为别名,这里beanClassName是learn.dto.Person
// Register an alias for the plain bean class name, if still possible,
// if the generator returned the class name plus a suffix.
// This is expected for Spring 1.2/2.0 backwards compatibility.
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);//beanClassName是learn.dto.Person
}
}
if (logger.isDebugEnabled()) {
logger.debug("Neither XML 'id' nor 'name' specified - " +
"using generated bean name [" + beanName + "]");
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//6、返回holder,即BeanDefinitionHolder对象。
//BeanDefinitionHolder参见:https://blog.csdn.net/cgsyck/article/details/88880196
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {
//1、parseState是模仿栈的数据结构,用于记录当前解析进度,方便错误信息输出,略
this.parseState.push(new BeanEntry(beanName));
//2、解析节点的class属性
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
try {
//3、解析节点的parent属性
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//4、创建BeanDefinition实例对象
AbstractBeanDefinition bd = createBeanDefinition(className, parent);//就是new GenericBeanDefinition
//5、解析节点的scope、singleton、abstrace、lazy-init、autowire、dependency-check、
//depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、
//factory-bean属性,把这些属性的值设置到bd的相应属性里。
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//方法代码下面不列了
//6、解析节点下的<description>子节点,把该子节点的值设置到相应属性里
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//7、解析节点下的子节点的标签值是否等于meta,没细看,暂时略
parseMetaElements(ele, bd);
//8、解析节点下的子节点的标签值是否等于lookup-method,暂时略
//参见:https://blog.csdn.net/weixin_46909938/article/details/138535529
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//9、解析节点下的子节点的标签值是否等于replaced-method,暂时略
//参见:https://www.jianshu.com/p/06f71d241866
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//10、解析构造参数
parseConstructorArgElements(ele, bd);
//11、解析bean的属性
parsePropertyElements(ele, bd);
//12、解析qualifier子元素,暂时略
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());//这个Resource对象就是applicationContext
//一开始把路径字符串得到的Resource对象
bd.setSource(extractSource(ele));//暂时略
return bd;
}
catch (ClassNotFoundException ex) {
error("Bean class [" + className + "] not found", ele, ex);
}
catch (NoClassDefFoundError err) {
error("Class that bean class [" + className + "] depends on not found", ele, err);
}
catch (Throwable ex) {
error("Unexpected failure during bean definition parsing", ele, ex);
}
finally {
this.parseState.pop();
}
return null;
}
protected AbstractBeanDefinition createBeanDefinition(String className, String parentName){
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
//this.readerContext.getBeanClassLoader()就是xmlReader.getBeanClassLoader(),此处
//的ClassLoader为null
}
//BeanDefinitionReaderUtils.createBeanDefinition()
public static AbstractBeanDefinition createBeanDefinition(
String parentName, String className, ClassLoader classLoader) throws ClassNotFoundException {
GenericBeanDefinition bd = new GenericBeanDefinition();
bd.setParentName(parentName);
if (className != null) {
if (classLoader != null) {
bd.setBeanClass(ClassUtils.forName(className, classLoader));
}
else {//正常走这个分支
bd.setBeanClassName(className);
}
}
return bd;
}
六、beanFactory注册BeanDefinition
//BeanDefinitionReaderUtils.registerBeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
//调用beanFactory对象的方法来进行注册,详细参见附录2
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String aliase : aliases) {
registry.registerAlias(beanName, aliase);
}
}
}

Ⅱ、总结:
spring框架通过documentReader和delegate完成了document到BeanDefinition的转换工作。

附录:
1、delegate对象的装饰bdHolder对象方法

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) {
return decorateBeanDefinitionIfRequired(ele, definitionHolder, null);
}
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {
BeanDefinitionHolder finalDefinition = definitionHolder;
// Decorate based on custom attributes first.
NamedNodeMap attributes = ele.getAttributes();
for (int i = 0; i < attributes.getLength(); i++) {
Node node = attributes.item(i);
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
// Decorate based on custom nested elements.
NodeList children = ele.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node node = children.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
}
}
return finalDefinition;
}

2、beanFactory注册beanDefinition过程

//DefaultListableBeanFactory.registerBeanDefinition
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");
//1、校验bd对象是否有效
//GenericBeanDefinition父类是AbstractBeanDefinition,所以会进入该分支
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
//validate方法内部校验规则
//1、为不能同时存在“方法覆盖methodOverrides”和“factoryMethodName”这两种配置项,
//2、如果配了方法覆盖,校验要覆盖的方法名在对应bean的class里有没有,没有报错
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
synchronized (this.beanDefinitionMap) {
Object oldBeanDefinition = this.beanDefinitionMap.get(beanName);
//按道理应该为null,想不到什么场景下会不为null
if (oldBeanDefinition != null) {
if (!this.allowBeanDefinitionOverriding) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
"': There is already [" + oldBeanDefinition + "] bound.");
}
else {
if (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
//正常进入该分支
else {
this.beanDefinitionNames.add(beanName);//加入到beanDefinitionNames
this.frozenBeanDefinitionNames = null;
}
this.beanDefinitionMap.put(beanName, beanDefinition);//加入到beanDefinitionMap
}
//重置当前bean
resetBeanDefinition(beanName);
}
//重置当前bean,即清空缓存
protected void resetBeanDefinition(String beanName) {
//1、这个不清楚,暂时略
// Remove the merged bean definition for the given bean, if already created.
clearMergedBeanDefinition(beanName);
// Remove corresponding bean from singleton cache, if any. Shouldn't usually
// be necessary, rather just meant for overriding a context's default beans
// (e.g. the default StaticMessageSource in a StaticApplicationContext).
//2、从缓存里销毁bean实例
destroySingleton(beanName);
//3、清空allBeanNamesByType和singletonBeanNamesByType
// Remove any assumptions about by-type mappings.
clearByTypeCache();//->this.allBeanNamesByType.clear();this.singletonBeanNamesByType.clear();
//4、把当前bean所有子递归的进行重置操作
// Reset all bean definitions that have the given bean as parent (recursively).
for (String bdName : this.beanDefinitionNames) {
if (!beanName.equals(bdName)) {
BeanDefinition bd = this.beanDefinitionMap.get(bdName);
if (beanName.equals(bd.getParentName())) {
resetBeanDefinition(bdName);
}
}
}
}
protected void clearMergedBeanDefinition(String beanName) {
this.mergedBeanDefinitions.remove(beanName);
}
public void destroySingleton(String beanName) {
// Remove a registered singleton of the given name, if any.
removeSingleton(beanName);
// Destroy the corresponding DisposableBean instance.
DisposableBean disposableBean;
synchronized (this.disposableBeans) {
disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
}
destroyBean(beanName, disposableBean);
}
protected void removeSingleton(String beanName) {
synchronized (this.singletonObjects) {
this.singletonObjects.remove(beanName);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.remove(beanName);
}
}
private void clearByTypeCache() {
this.allBeanNamesByType.clear();
this.singletonBeanNamesByType.clear();
}
posted @   bplan2010  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示