好了!这里又出现了新的类型 BeanDefinitionParserDelegate 干什么用的?不过我知道这肯定和 XML 解析有关,所以不容错过!于是乎,简单浏览了一下它的实现(怕进入代码丛林!),我的天啊,我找到正题了:
public class BeanDefinitionParserDelegate {
public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans" ;
public static final String BEAN_NAME_DELIMITERS = ",; " ;
public static final String TRUE_VALUE = "true" ;
public static final String FALSE_VALUE = "false" ;
public static final String DEFAULT_VALUE = "default" ;
public static final String DESCRIPTION_ELEMENT = "description" ;
public static final String AUTOWIRE_NO_VALUE = "no" ;
public static final String AUTOWIRE_BY_NAME_VALUE = "byName" ;
public static final String AUTOWIRE_BY_TYPE_VALUE = "byType" ;
public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor" ;
public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect" ;
public static final String DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE = "all" ;
public static final String DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE = "simple" ;
public static final String DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE = "objects" ;
public static final String NAME_ATTRIBUTE = "name" ;
…..
这不是我们在 Spring XML 配置文件中经常看到的 XML 属性名称吗!我又看看了下面一些方法!
protected void populateDefaults(DocumentDefaultsDefinition defaults, DocumentDefaultsDefinition parentDefaults, Element root) {
String lazyInit = root.getAttribute( DEFAULT_LAZY_INIT_ATTRIBUTE );
if ( DEFAULT_VALUE .equals(lazyInit)) {
lazyInit = parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE ;
}
defaults.setLazyInit(lazyInit);
String merge = root.getAttribute( DEFAULT_MERGE_ATTRIBUTE );
if ( DEFAULT_VALUE .equals(merge)) {
merge = parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE ;
}
defaults.setMerge(merge);
String autowire = root.getAttribute( DEFAULT_AUTOWIRE_ATTRIBUTE );
if ( DEFAULT_VALUE .equals(autowire)) {
autowire = parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE ;
}
defaults.setAutowire(autowire);
defaults.setDependencyCheck(root.getAttribute( DEFAULT_DEPENDENCY_CHECK_ATTRIBUTE ));
if (root.hasAttribute( DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE )) {
defaults.setAutowireCandidates(root.getAttribute( DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE ));
} else if (parentDefaults != null ) {
defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
}
if (root.hasAttribute( DEFAULT_INIT_METHOD_ATTRIBUTE )) {
defaults.setInitMethod(root.getAttribute( DEFAULT_INIT_METHOD_ATTRIBUTE ));
} else if (parentDefaults != null ) {
defaults.setInitMethod(parentDefaults.getInitMethod());
}
if (root.hasAttribute( DEFAULT_DESTROY_METHOD_ATTRIBUTE )) {
defaults.setDestroyMethod(root.getAttribute( DEFAULT_DESTROY_METHOD_ATTRIBUTE ));
} else if (parentDefaults != null ) {
defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
}
defaults.setSource( this . readerContext .extractSource(root));
}
这不就是解析的过程吗?咦?装入 BeanDefinition 中的逻辑在什么地方,我们不能在 Spring 代码其他地方直接使用这些配置信息啊,只能给它们包装到一个实体类啊(当数据结构过长,一般是用实体类来存储的,哈哈,我也明白 BeanDefinitio 的设计目的了!)我继续在这个类里面找:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
String id = ele.getAttribute( ID_ATTRIBUTE );
String nameAttr = ele.getAttribute( NAME_ATTRIBUTE );
List<String> aliases = new ArrayList<String>();
if (StringUtils.hasLength (nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray (nameAttr, BEAN_NAME_DELIMITERS );
aliases.addAll(Arrays.asList (nameArr));
// 别名的解析
}
String beanName = id;
if (!StringUtils.hasText (beanName) && !aliases.isEmpty()) {
beanName = aliases.remove(0); // 第一个作为 Bean 的默认名称 ,very good!
if ( logger .isDebugEnabled()) {
logger .debug( "No XML 'id' specified - using '" + beanName +
"' as bean name and " + aliases + " as aliases" );
}
}
if (containingBean == null ) {
//check bean 名是不是在容器中唯一
checkNameUniqueness(beanName, aliases, ele);
}
// 在这里具体创建 beanDefinition 实例,非常好的逻辑,代码逻辑清晰
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null ) {
if (!StringUtils.hasText (beanName)) {
try {
if (containingBean != null ) {
// 没有 Bean 名的话,就生成一个 ,. 供内部使用
beanName = BeanDefinitionReaderUtils.generateBeanName (
beanDefinition, this . readerContext