posts - 28,  comments - 15,  trackbacks - 0
2.2.3 资源定位、解释
2.2.3.1 资源定位加载与容器的关系
     loadBeanDefinitions方法主要是加载BeanDefinition,而BeanDefinition的定义是来自于一组资源的,要加载BeanDefinition,Spring首先要加载、解释这些资源,资源的定位、加载由ResourceLoader与ResourcePatternResolver负责。
在loadBeanDefinitions方法分析之前,我们先来了解下容器与ResourceLoader之间的联系。ResourceLoader是资源加载器接口;ResourcePatternResolver是资源模式解释器接口,它把一个定位模式(例如,ant样式模式)转变为Resource对象; ResourcePatternResolver扩展自ResourceLoader,因此也可以说一个ResourcePatternResolver的实现在同时具备资源模式解释的同时,也具备资源的加载功能呢(关于继承结构参见图1)。
那么容器与ResourceLoader、ResourcePatternResolver在结构上有什么联系呢?见如下代码:
接口ApplicationContext与ResourcePatternResolver:
public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,MessageSource,ApplicationEventPublisher,
ResourcePatternResolver{
……
}


抽象类AbstractApplicationContext与ResourceLoader、ResourcePatternResolver:
public abstract class AbstractApplicationContext 
extends DefaultResourceLoader
implements ConfigurableApplicationContext, DisposableBean{

//意味着FileSystemXmlApplicationContext在创建时,就已经拥有resolver实例,见灰色部分
pivate ResourcePatternResolver resourcePatternResolver;

public AbstractApplicationContext(ApplicationContext parent) {
        
this.parent = parent;
        
this.resourcePatternResolver = getResourcePatternResolver();
}


protected ResourcePatternResolver getResourcePatternResolver() {
        
return new PathMatchingResourcePatternResolver(this);
}


//解释返回资源的功能不是其自身实现,而是通过调用resourcePatternResolver提供
public Resource[] getResources(String locationPattern) throws IOException {
        
return this.resourcePatternResolver.getResources(locationPattern);
    }


    
    
    由代码可以看出,资源模式解释器在容器创建时就已经创建,资源模式解释器由PathMatchingResourcePatternResolver担当。AbstractApplicationContext继承于DefaultResourceLoader,因此AbstractApplicationContext也具备了资源加载的功能。同时ApplicationContext扩展了ResourcePatternResolver接口,所以ApplicationContext的实现类对外表现的Loader应该为ResourcePatternResolver。通俗来讲,就是说容器具备资源模式解释的功能,并能对一资源位置进行加载,参看图-1理解一下。
     知道了容器与ResourceLoader之间的联系,我们继续loadBeanDefinitions方法的分析。

2.2.3.2 loadBeanDefinitions方法分析
loadBeanDefinitions是由类AbstractXmlApplicationContext实现的。它在这里主要做了以下功能:
    把加载Definition(从字面上就能看出,其是对xml中的bean的定义)的工作委托给XmlBeanDefinitionReader,XmlBeanDefinitionReader来进行资源的定位,
资源的加载。
    
AbstractXmlApplicationContext.loadBeanDefinitions()代码:
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
/**这里的beanFactory是以BeanDefinitionRegistry的角色作为参数传入到XmlBeanDefinitionReader中的,由于DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此,beanFactory具备了BeanDefination的注册功能*/
XmlBeanDefinitionReader beanDefinitionReader 
= new XmlBeanDefinitionReader(beanFactory);
//为reader设置resourceloader,参看类图DefaultListableBeanFactory继承自DefaultResourceLoader
beanDefinitionReader.setResourceLoader(this);    beanDefinitionReader.setEntityResolver(newResourceEntityResolver(this));

    initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
}


/**从下段代码可以看出,虽然容器具备资源的加载的功能,但是spring并没有在容器类中直接处理资源加载的工作,而是把这项工作委托给XmlBeanDefinitionReader。XmlBeanDefinitionReader是XML bean definitions的reader,它把实际的XML文档读取任务交给了DefaultBeanDefinitionDocumentReader来完成.*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
       
        Resource[] configResources 
= getConfigResources();
        
if (configResources != null{
            reader.loadBeanDefinitions(configResources);
        }

        String[] configLocations 
= getConfigLocations();
        
if (configLocations != null{
              
//由XmlBeanDefinitionReader来加载beanDefinition
            reader.loadBeanDefinitions(configLocations);
        }

}


/***以下方法来自于AbstractBeanDefinitionReader,该类是XmlBeanDefinitionReader的超类***/
//由一组指定的资源位置,加载资源
public int loadBeanDefinitions(String[] locations) throws BeanDefinitionStoreException {
        Assert.notNull(locations, 
"Location array must not be null");
        
int counter = 0;
        
for (int i = 0; i < locations.length; i++{
            counter 
+= loadBeanDefinitions(locations[i]);
        }

        
return counter;
}

//加载特定资源位置下的资源
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
        
return loadBeanDefinitions(location, null);
}


public int loadBeanDefinitions(String location, Set actualResources) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader 
= getResourceLoader();
    ……
        
if (resourceLoader instanceof ResourcePatternResolver) {
            
try //这里进行资源位置解释成资源(Resource)关于资源定位解释成资源,请参看后面的“资源定位分析”
                Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);

                
int loadCount = loadBeanDefinitions(resources);
                
if (actualResources != null{
                    
for (int i = 0; i < resources.length; i++{
                        actualResources.add(resources[i]);
                    }

                }

                
return loadCount;
            }

            
catch (IOException ex) {
                …….
        }
else{
              ……. 
         }

}


/**以下方法来自XmlBeanDefinitionReader**/
//加载指定的resource,由上面的方法调用,主要对resource进行编码处理
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
        
return loadBeanDefinitions(new EncodedResource(resource));
}


//加载经过编码后的Resource
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
         ……
        
//谁能说说这里使用ThreadLocal的好处是什么呢?
        Set currentResources = (Set) this.resourcesCurrentlyBeingLoaded.get();
        
if (currentResources == null{
            currentResources 
= new HashSet(4);
            
this.resourcesCurrentlyBeingLoaded.set(currentResources);
        }

        
if (!currentResources.add(encodedResource)) {
            ……
        }

        
try {
            InputStream inputStream 
= encodedResource.getResource().getInputStream();
            
try {
                InputSource inputSource 
= new InputSource(inputStream);
                
if (encodedResource.getEncoding() != null{
                inputSource.setEncoding(encodedResource.getEncoding());
                }

                         
//真正的加载工作在这里进行
                return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }

            
finally {
                inputStream.close();
            }

        }

        
catch (IOException ex) {
            ……
        }

        
finally {
            ……
        }

    }



2.2.3.3资源定位(resource location)分析
     资源定位的定义主要包含两类:单一的资源路径带有占位符的复合资源路径,其中后一种Spring支持ant-style样式的定义,例如classpath*:/WEF-INF/*-con.xml。无论是哪种类型的资源定位,最后都需要被解释成Resource(资源)。其中第一种由DefaultResourceLoader负责,其实现是通过资源定位尝试构造URL,然后把URL封装成URLResource;后一种由PathMatchingResourcePatternResolver负责,其主要处理ant-style样式的资源定位,其处理的资源主要包括两类:文件系统文件、jar文件(jar、zip、wsjar等),其返回的资源可能包括URLResource、FileSystemResource。

 

PathMatchingResourcePatternResolver资源定位:

/** 单独定位,即location类似于“c:/zhangxl/doc/12.txt”样式 **/
public Resource getResource(String location) {
        
return getResourceLoader().getResource(location);
}


/** ant-style样式定位(包含单独定位),类似与classpath*:/WEF-INF/*-context.xml **/
public Resource[] getResources(String locationPattern) throws IOException {
        Assert.notNull(locationPattern, 
"Location pattern must not be null");
//检查是否以类路径为前缀(classpath*:),例如classpath*:/WEF-INF/*-context.xml    
if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
// a class path resource (multiple resources for same name possible)
//定位模式是否采用了ant-style,即采用*或者?占位符的
    if (getPathMatcher().isPattern(
locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length())))
{
// a class path resource pattern 
// findPathMatchingResources处理的策略是先获取根路径,然后递归匹配各个子目录下的文件,其处理的文件类型主要有两大类:文件系统文件、jar文件(包括jar、zip、wsjar等)。其返回的Resource主要包括URLResource,FileSystemResource实例.        
            return findPathMatchingResources(locationPattern);
    }

else {
                
// all class path resources with the given name
     
// findAllClassPathResources的处理策略主要是通过ClassLoader获得URL,然后构造URLResource            
return findAllClassPathResources(locationPattern
.substring(CLASSPATH_ALL_URL_PREFIX.length()));
            }

        }

        
else {
            
// Only look for a pattern after a prefix here
            
// (to not get fooled by a pattern symbol in a strange prefix).
            int prefixEnd = locationPattern.indexOf(":"+ 1;
            
if (getPathMatcher().isPattern(
locationPattern.substring(prefixEnd))) 
{
                
// a file pattern
                return findPathMatchingResources(locationPattern);
            }

            
else {
                
// a single resource with the given name
                   
//由DefaultResourceLoader处理,返回UrlResource
                return new Resource[] {getResourceLoader().getResource(locationPattern)};
}

        }

    }


DefaultResourceLoader资源定位:
public Resource getResource(String location) {
        Assert.notNull(location, 
"Location must not be null");
        
if (location.startsWith(CLASSPATH_URL_PREFIX)) {
            
return new ClassPathResource(
location.substring(CLASSPATH_URL_PREFIX.length())
, getClassLoader());
        }

        
else {
            
try {
                
// 其只是尝试把location转化为URL
                URL url = new URL(location);
                
return new UrlResource(url);
            }

            
catch (MalformedURLException ex) {
                
// No URL -> resolve as resource path.
                return getResourceByPath(location);
            }

        }

    }


 2.2.4 资源的解释以及BeanDefinition的注册
2.2.4.1 doLoadBeanDefinitions方法分析

    我们在2.2.3.2节中提到,doLoadBeanDefinitions方法真正进行了资源的加载、解释工作。下面我们看看doLoadBeanDefinitions的实现。
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)throws BeanDefinitionStoreException {
        
try {
//获取验证模式,如果未配置将采用detected mode
            int validationMode = getValidationModeForResource(resource);            //Resource被加载为Document
            Document doc = this.documentLoader.loadDocument(
                    inputSource, getEntityResolver(), 
this.errorHandler, validationMode, isNamespaceAware());
//解释resource为BeanDefinition,并注册BeanDefinition
            return registerBeanDefinitions(doc, resource);
        }

}


public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
        
/**这里创建BeanDefinitionDocumentReader接口实例,该实例由DefaultBeanDefinitionDocumentReader担当,其主要依据“spring-beans”DTD和XSD来读取BeanDefinition*/
BeanDefinitionDocumentReader documentReader 
= createBeanDefinitionDocumentReader();
        
int countBefore = getRegistry().getBeanDefinitionCount();
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
        
return getRegistry().getBeanDefinitionCount() - countBefore;
    }




2.2.4.1.1 BeanDefinitionDocumentReader
对加载的Document的处理以及Bean注册
DefaultBeanDefinitionDocumentReader的代码:
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
        
this.readerContext = readerContext;

        Element root 
= doc.getDocumentElement();
    
//由BeanDefinitionParserDelegate协助完成xml到BeanDefinition的解释工作
        BeanDefinitionParserDelegate delegate = 
createHelper(readerContext, root);

        preProcessXml(root);
//空函数实现
        
//把Element解释为BeanDefinition,并注册
        parseBeanDefinitions(root, delegate);
        postProcessXml(root);
//空函数
}


protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
//判断节点是否属于命名空间http://www.springframework.org/schema/beans
        if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
            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;
                    String namespaceUri 
= ele.getNamespaceURI();
                    
if (delegate.isDefaultNamespace(namespaceUri)) {
                         
//对xml document的解释工作在这里完成
                        parseDefaultElement(ele, delegate);
                         
                    }

                    
else {
                        delegate.parseCustomElement(ele);
                    }

                }

            }

        }

        
else {
            
//解释定制元素,例如aop、context等。
            delegate.parseCustomElement(root);
        }

}


private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        
//解释import标签
        if (DomUtils.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }

        
else if (DomUtils.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }

        
//这里是真正的开始解释bean节点
        else if (DomUtils.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }

}


protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
/**把Element解释成GenericBeanDefinition(BeanDefinition的具体实现),并创建新的BeanDefinitionHolder,并把解释的definition、beanName、aliases封装进BeanDefinitionHolder*/
BeanDefinitionHolder bdHolder 
= delegate.parseBeanDefinitionElement(ele);//实现参看后面的parseBeanDefinitionElement方法分析
        if (bdHolder != null{
            bdHolder 
= delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//对定制的一些配置进行装饰性解释,例如aop
            try {
//注册BeanDefinition
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder,       getReaderContext().getRegistry());
            }

            
catch (BeanDefinitionStoreException ex) {
                ……
            }

            
// Send registration event.
            getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
        }

    }


/*解释的过程主要完成对id、name、parent、lazy-init、singleton等属性的解释,并把相关属性设置到BeanDefinition中。接下来我们看看BeanDefinition的注册,即BeanDefinitionReaderUtils.registerBeanDefinition的实现:*/
public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            
throws BeanDefinitionStoreException {

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

        
//注册bean的别名
        String[] aliases = definitionHolder.getAliases();
        
if (aliases != null{
            
for (int i = 0; i < aliases.length; i++{
                registry.registerAlias(beanName, aliases[i]);
            }

        }

    }


public class DefaultListableBeanFactory 
extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry {

/**Whether to allow re-registration of a different definition with the same name */
    
private boolean allowBeanDefinitionOverriding = true;

/** Whether to allow eager class loading even for lazy-init beans */
    
private boolean allowEagerClassLoading = true;

/** Whether bean definition metadata may be cached for all beans */
    
private boolean configurationFrozen = false;
/** Map of bean definition objects, keyed by bean name *///以ConcurrentMap存储BeanDefinition
private final Map beanDefinitionMap = 
CollectionFactory.createConcurrentMapIfPossible(
16);

/** List of bean definition names, in registration order *///存储注册的beanName
    private final List beanDefinitionNames = new ArrayList();

    
/** Cached array of bean definition names in case of frozen configuration *///存储被冻结的beanName
    private String[] frozenBeanDefinitionNames;


public void registerBeanDefinition(String beanName, 
BeanDefinition beanDefinition)
            
throws BeanDefinitionStoreException {

        
if (beanDefinition instanceof AbstractBeanDefinition) {
            
try {
                ((AbstractBeanDefinition) beanDefinition).validate();
            }

            
catch (BeanDefinitionValidationException ex) {
                ……
            }

        }


        
synchronized (this.beanDefinitionMap) {
            Object oldBeanDefinition 
= this.beanDefinitionMap.get(beanName);
            
if (oldBeanDefinition != null{
               
//如果相同名字的BeanDefinition已经存在,且不允许覆盖,抛出异常。
                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);
                
this.frozenBeanDefinitionNames = null;
            }

            
this.beanDefinitionMap.put(beanName, beanDefinition);

            resetBeanDefinition(beanName);
        }

    }


protected void resetBeanDefinition(String beanName) {
// 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).
        synchronized (getSingletonMutex()) {//
            destroySingleton(beanName);
        }


        
// Reset all bean definitions that have the given bean as parent
        
// (recursively).
        for (Iterator it = this.beanDefinitionNames.iterator(); it.hasNext();) {
            String bdName 
= (String) it.next();
            
if (!beanName.equals(bdName)) {
                BeanDefinition bd 
= (BeanDefinition) this.beanDefinitionMap.get(bdName);
                
if (beanName.equals(bd.getParentName()))  {
                    resetBeanDefinition(bdName);
                }

            }

        }

}



parseBeanDefinitionElement方法分析
 该方法主要针对bean标签进行解释处理,解释后的信息封装到GenericBeanDefinition中,然后把beanName、alias、GenericBeanDefinition封装到BeanDefinitionHolder中.
 

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {

      

       String id = ele.getAttribute(ID_ATTRIBUTE);//取得id属性

//取得name属性

       String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

       List aliases = new ArrayList();//aliase属性 例如<alias name="fromName" alias="toName"/>

       if (StringUtils.hasLength(nameAttr)) {

//如果name属性存在,则把name的值分解,存储到aliases集合中

           String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, BEAN_NAME_DELIMITERS);

           aliases.addAll(Arrays.asList(nameArr));

       }

 

       String beanName = id;//默认id的值作为beanName

       if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {//如果id不存在,且aliases不为空,那么以aliases中的第一个作为beanName

           beanName = (String) aliases.remove(0);

           if (logger.isDebugEnabled()) {

              logger.debug("No XML 'id' specified - using '" + beanName +

                     "' as bean name and " + aliases + " as aliases");

           }

       }

 

       if (containingBean == null) {

           /*检查在一个文件中,beanName或者alias是否有重复的,如果有重复的报告错误,无重复,则把当前的beanNamealias记录到Set*/

           checkNameUniqueness(beanName, aliases, ele);

       }

       

//bean的详细解释,主要包括常见的classparentlazy-initsingleton等属性

       AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

       if (beanDefinition != null) {

           if (!StringUtils.hasText(beanName)) {

              try {

                  if (containingBean != null) {

                     beanName = BeanDefinitionReaderUtils.generateBeanName(

                            beanDefinition, this.readerContext.getRegistry(), true);

                  }

                  else {

/*容器生成beanName,其规则如下:

如果beanDefinition存在className,则以"className#编号"或者"className"作为beanName

如果beanDefinition不存在className,beanDefinition存在parentName,则以"parentName$child#编号"或者"parentName$child"作为beanName;

如果beanDefinition不存在className,beanDefinition存在factorybeanName,则以"factoryBeanName$created#编号"或者"factoryBeanName$created"作为beanName;

注意,编号是通过查询容器是否包含beanName,然后累加获得的*/

                  beanName = this.readerContext.generateBeanName(beanDefinition);

String beanClassName = beanDefinition.getBeanClassName();

                     if (beanClassName != null &&

                            beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&

                            !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {

                         aliases.add(beanClassName);

                     }

                  }

                  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);

           //最后封装为BeanDefinitionHoler返回

           return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);

       }

 

       return null;

public AbstractBeanDefinition parseBeanDefinitionElement(

           Element ele, String beanName, BeanDefinition containingBean) {

       String className = null;//解释class属性

       if (ele.hasAttribute(CLASS_ATTRIBUTE)) {

           className = ele.getAttribute(CLASS_ATTRIBUTE).trim();

       }

       String parent = null;

       if (ele.hasAttribute(PARENT_ATTRIBUTE)) {//parent属性

           parent = ele.getAttribute(PARENT_ATTRIBUTE);

       }

 

       try {

//beanid作为参数封装到BeanEntry中;ParseStateStack作为存储数据结构来存储Bean的解释状态

           this.parseState.push(new BeanEntry(beanName)); 

          

//创建了GenericBeanDefinition,并为其设置parent=='parent',beanClass=='class',beanClassName属性

           AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(

                  parent, className, this.readerContext.getBeanClassLoader());

 

           if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {//解释scope

              bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));

              if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {

                  error("Specify either 'scope' or 'singleton', not both", ele);

              }

           }

           else if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {//singleton

    bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ?

                     BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE);

           }

           else if (containingBean != null) {

                  bd.setScope(containingBean.getScope());

           }

 

           if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {//解释abstract

              bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));

           }

 

           String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);//解释lazy-init

           if (DEFAULT_VALUE.equals(lazyInit) && bd.isSingleton()) {

              // Just apply default to singletons, as lazy-init has no meaning for prototypes.

              lazyInit = this.defaults.getLazyInit();

           }

           bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

 

           String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);//解释自动装配模式

           bd.setAutowireMode(getAutowireMode(autowire));

 

           String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);

           bd.setDependencyCheck(getDependencyCheck(dependencyCheck));//解释依赖检查

 

           if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {

              String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);//解释depends-on

              bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, BEAN_NAME_DELIMITERS));

           }

 

           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));

           }

 

           if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {

              bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));

           }

 

           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);

              }

           }

 

           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);

              }

           }

 

           if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {//解释工厂方法属性

              bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));

           }

           if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {//解释工厂bean属性

              bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));

           }

 

           bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

 

           parseMetaElements(ele, bd);

           /**解释lookup-method(方法注入的一种),还记得吗,使用lookup-method能够覆盖bean标签指定的bean的抽象method(methodmethod标签指定),主要针对singleton引用一个prototype的情形*/

           parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

           //解释replace-method(方法注入的一种)

           parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

 

           parseConstructorArgElements(ele, bd);

           /**这里把解释出来的属性值,ref[RuntimeBeanReference]list[ManagedList]set[ManagedSet]mapproperties,封装到PropertyValue

       然后把PropertyValue加入到BeanDefinition*/

           parsePropertyElements(ele, bd);

           parseQualifierElements(ele, bd);

 

           bd.setResource(this.readerContext.getResource());

           bd.setSource(extractSource(ele));

 

           return bd;

}





posted on 2012-01-30 14:24 zhangxl 阅读(526) 评论(0)  编辑  收藏 所属分类: Spring

只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(1)

随笔分类(17)

随笔档案(28)

文章分类(30)

文章档案(30)

相册

收藏夹(2)

hibernate

java基础

mysql

xml

关注

压力测试

算法

最新随笔

搜索

  •  

积分与排名

  • 积分 - 95498
  • 排名 - 602

最新评论

阅读排行榜

评论排行榜