Spring源码解析之默认标签的解析(一)

来源:互联网 发布:bitcomet mac版 编辑:程序博客网 时间:2024/05/25 16:39

二、默认标签的解析

spring中的标签包含默认标签和自定义标签两种,而两种的标签的解析方法打不通,这边重点详细的分析默认标签的解析过程
默认标签解析是在DefaultBeanDefinitionDocumentReader类的parseDefaultElement方法中,方法中对4中不同的标签做了不同的处理(import、alias、bean和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);
    }
}

1、bean标签的解析及注册

a、bean标签是4中标签中最为复杂的,在processBeanDefinition方法中实现了解析及注册。源码如下


   protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// 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));
}
   }

 方法的大致逻辑
   ①:首先委托BeanDefinitionParserDelegate 类的parseBeanDefinitionElement方法进行元素解析,返回BeanDefinitionHolder 实例别的Holder,
此时bdHolder实例已经包含了我们配置的各种属性了,例如class、name、id、alias之类的属性
   ②:当返回的bdHolder不为空的情况若存在默认标签的对子节点下再有自定义属性,还需要再次对自定义标签进行解析
   ③:解析完成后,需要对解析后的bdHoler进行注册,同样,注册操作委托给了BeanDefinitionReaderUtils的registerBeanDefinition方法
   ④:终于归于发出相应,通知想关的监听器,这个bean已经加载完成了

  b、解析BeanDefinition
   这边对各个操作做具体分析,先从元素解析及信息提取开始,也就是BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);。源码如下:
   public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
   }
   public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
//解析id
String id = ele.getAttribute(ID_ATTRIBUTE);
//解析name
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
//分割name属性,用,; 进行分割
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}


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");
}
}
if (containingBean == null) {
checkNameUniqueness(beanName, aliases, ele);
}
//解析bean的其他属性,并将属性数据封装到AbstractBeanDefinition 中
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
//如果不存在beanName那么根据Spring提供的命名规则来为当前的bean命名
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
beanName = this.readerContext.generateBeanName(beanDefinition);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
liases.add(beanClassName);
}
}
if (logger.isDebugEnabled()) {
ogger.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);
//获取到的信息封装到BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}


return null;
   }

以上就是解析标签的全过程,总共4个步骤
    ①:提取元素中的id和name 属性
    ②:进一步解析其他所有属性并统一封装到GenericBeanDefinition 类型的实例中
    ③:如果检测到bean没有beanName,那么会使用默认的规则生成beanName
    ④:将获取到的信息封装到BeanDefinitionHolder

 进一步查看②的过程中:源码如下
 
 public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, BeanDefinition containingBean) {

this.parseState.push(new BeanEntry(beanName));
String className = null;
//解析class属性
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}


try {
//解析parent属性
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
//创建承载属性的AbstractBeanDefinition 类型的GenericBeanDefinition  实例
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
//用编码解析bean的各中属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
//提取description
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//解析元数据
parseMetaElements(ele, bd);
//解析lookup-method属性
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解析replace-method属性
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
//解析构造函数参数
parseConstructorArgElements(ele, bd);
//解析property子元素
parsePropertyElements(ele, bd);
//解析qualifier 子元素
parseQualifierElements(ele, bd);


bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
//返回AbstractBeanDefinition,其中包含着bean的各种属性
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;
}

以上bean标签的所有都解析了,还有一个复杂的的属性还需要进一步解析
       ①:创建用于属性承载的BeanDefinition
            BeanDefinition是一个接口,在这个接口有三种实现:RootBeanDefinition,ChildBeanDefinition,以及GenericBeanDefinition。
        三个都继承了AbstractBeanDefinition,BeanDefinition是配置文件<bean>元素,BeanDefinition中提供了<bean>标签拥有的相关配置。
            在配置文件中可以定义父<bean>和子<bean>,父<bean>用RootBeanDefinition标识,而子类<bean>用的是ChildBeanDefinition。没有
        父类的<bean>也是用RootBeanDefinition
            spring通过BeanDefinition 将配置文件的<bean>转化为容器的内部表示,并注册到BeanDefinitionRegistry中。BeanDefinitionRegistry
        就像是配置文件中的内存数据库,以map的的形式保存

createBeanDefinition(className, parent);方法的代码如下(创建承载属性的AbstractBeanDefinition 类型的GenericBeanDefinition  实例):
        protected AbstractBeanDefinition createBeanDefinition(String className, String parentName)
throws ClassNotFoundException {
return BeanDefinitionReaderUtils.createBeanDefinition(
parentName, className, this.readerContext.getBeanClassLoader());
}
    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;
}

②:创建完bean信息的承载实例后,便开始进行bean信息的各种属性解析了。parseBeanDefinitionAttributes方法就是解析bean的各种属性
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
BeanDefinition containingBean, AbstractBeanDefinition bd) {
//解析scope属性
if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
}
else if (containingBean != null) {
//在嵌入beanDefinition情况下且没有单独制定scope 属性则使用父类默认的属性
bd.setScope(containingBean.getScope());
}
//解析abstract 属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
//解析lazy-init属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
//设置autowire 属性
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
//设置dependency-check属性
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);
bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
//解析depends-on属性
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
//解析autowire-candidate属性
String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(autowireCandidate)) {
String candidatePattern = this.defaults.getAutowireCandidates();
if (candidatePattern != null) {
String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern);
bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName));
}
}
else {
bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
}
//解析primary属性
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
//解析init-method属性
if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
if (!"".equals(initMethodName)) {
bd.setInitMethodName(initMethodName);
}
}
else {
if (this.defaults.getInitMethod() != null) {
bd.setInitMethodName(this.defaults.getInitMethod());
bd.setEnforceInitMethod(false);
}
}
//解析destroy-method属性
if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
if (!"".equals(destroyMethodName)) {
bd.setDestroyMethodName(destroyMethodName);
}
}
else {
if (this.defaults.getDestroyMethod() != null) {
bd.setDestroyMethodName(this.defaults.getDestroyMethod());
bd.setEnforceDestroyMethod(false);
}
}
//解析factory-method属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
//解析factory-bean 属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}


return bd;
}

③:解析子元素meta
<bean id="myTestBean" class="bean.MyTestBean">
<meta key=testStr" value="aaaa"/>
</bean>
        解析meta源码如下:
public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
//获取当前节点的所有子元素
NodeList nl = ele.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//提取meta
if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
Element metaElement = (Element) node;
String key = metaElement.getAttribute(KEY_ATTRIBUTE);
String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
attribute.setSource(extractSource(metaElement));
//记录信息
attributeAccessor.addMetadataAttribute(attribute);
}
}
}

④:解析子元素lookup-method
lookup-method主要的作用就是实现依赖注入,lookup-method的使用方法:
public abstract class GetBeanTest{
    public void showMe(){
    this.getBean().showMe();
    }
    public abstract User getBean();
}
       <bean id="getBeanTest" class="test.lookup.app.GetBeanTest">
            <lookup-method name="getBean" bean="teacher"/>
       </bean>
       <bean id="teacher" class="test.lookup.bean.Teacher"/>
       </bean>
       源码如下:
       public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//仅当在spring 默认bean 的子元素下且为<lookup-method 时有效
if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
Element ele = (Element) node;
//获取要修改的方法
String methodName = ele.getAttribute(NAME_ATTRIBUTE);
//获取配置返回的bean
String beanRef = ele.getAttribute(BEAN_ELEMENT);
LookupOverride override = new LookupOverride(methodName, beanRef);
override.setSource(extractSource(ele));
overrides.addOverride(override);
}
}
}
       解析lookup-method 的源码和解析meta差不多,最大的区别上就是判断条件不同,这边是LOOKUP_METHOD_ELEMENT,。还有就是在数据
       存储是使用LookupOverride 类型的实现进行数据承载并记录在AbstractBeanDefinition中methodOverrides属性中

⑤:解析子元素replaced-method
  这个方法主要的作用是方法替换
       源码如下:
       public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//仅当在Spring 默认bean 的子元素下且为<replaced-method 
if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
Element replacedMethodEle = (Element) node;
//提取要替换的旧的方法
String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
//提取对应的新的替换方法
String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
// Look for arg-type match elements.
List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
for (Element argTypeEle : argTypeEles) {
//记录参数
String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
if (StringUtils.hasText(match)) {
replaceOverride.addTypeIdentifier(match);
}
}
replaceOverride.setSource(extractSource(replacedMethodEle));
overrides.addOverride(replaceOverride);
}
}
}
        解析replaced-method方法和解析lookup-method都是一样把数据记录在AbstractBeanDefinition的methodOverrides属性中

注:后续内容在Spring源码解析之默认标签的解析(二)中

阅读全文
0 0
原创粉丝点击