今天看了一下 BeanDefinitionParserDelegate 这个类,这个类是用来解析spring的xml配置文件中的bean的委托类,通过分析这个类,可以给 bean 的属性合理的值。
对于 bean 属性的解析,大部分是在 parseBeanDefinitionAttributes 方法执行,下为方法的定义:
public AbstractBeanDefinition parseBeanDefinitionAttributes(org.w3c.dom.Element ele,java.lang.String beanName,BeanDefinition containingBean,AbstractBeanDefinition bd)
首先是id和name属性,这个貌似没有过多的限制;如果id没有定义,会使用name的第一个值;然后name可以使用多值,中间以“,; ”(逗号、分号、空格)分割。id和name的解析在 parseBeanDefinitionElement 方法中,代码定义如下:
String id = ele.getAttribute(ID_ATTRIBUTE); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); List<String> aliases = new ArrayList<String>(); if (StringUtils.hasLength(nameAttr)) { // 这个 MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; " String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr,MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); } String beanName = id; // 没有id,但是有name if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { // 使用name中的第一个 beanName = aliases.remove(0); if (logger.isDebugEnabled()) { logger.debug("No XML 'id' specified - using '" + beanName + "' as bean name and " + aliases + " as aliases"); } } ...
然后是class和parent,这两个属性在parseBeanDefinitionElement方法中:
String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { // class 因为要使用反射调用,所以,进行了去 空格 的处理操作 className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); } try { // parent String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); } AbstractBeanDefinition bd = createBeanDefinition(className,parent); parseBeanDefinitionAttributes(ele,beanName,containingBean,bd); // description bd.setDescription(DomUtils.getChildElementValueByTagName(ele,DESCRIPTION_ELEMENT)); ...对于description,这是一个子标签,加注释用的,不过在国内都喜欢在标签上使用<!-- xx -->这种形式。
最后就是最重要的,parseBeanDefinitionAttributes方法中定义了大部分属性,下面进行一个一个的分析:
1. scope、singleton
if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { // Spring 2.x "scope" attribute 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)) { // Spring 1.x "singleton" attribute bd.setScope(TRUE_VALUE.equals(ele.getAttribute(SINGLETON_ATTRIBUTE)) ? BeanDefinition.SCOPE_SINGLETON : BeanDefinition.SCOPE_PROTOTYPE); } else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. bd.setScope(containingBean.getScope()); }
第一个if,如果存在 scope 属性的同时,还存在 singleton属性,就会报错;
第二个if,是建立在没有scope属性的前提上的,可以理解为:singleton == true?scope = singleton : scope = prototype;
第三个if,如果含有内部 bean ,则使用内部bean 的scope (此处待验证);
2. abstract
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); }
true 或者 false ;
3. lazy-init
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
默认值为default,如果为 default,会被转为 false,所以配置时,default == false;
4. autowire
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire));
默认为 default,得到后在getAutowireMode方法进行处理,返回值为int,getAutowireMode代码如下:
String att = attValue; if (DEFAULT_VALUE.equals(att)) { att = this.defaults.getAutowire(); // att 被赋值为 no } int autowire = AbstractBeanDefinition.AUTOWIRE_NO; // 0 if (AUTOWIRE_BY_NAME_VALUE.equals(att)) { // byName autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME; // 1 } else if (AUTOWIRE_BY_TYPE_VALUE.equals(att)) { // byType autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE; // 2 } else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(att)) { // constructor autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR; // 3 } else if (AUTOWIRE_AUTODETECT_VALUE.equals(att)) { // autodetect autowire = AbstractBeanDefinition.<del>AUTOWIRE_AUTODETECT</del>; // 4 } // Else leave default value. return autowire;
可以看出,default 在起始被 更改 为 no,然后才进行别的处理,而 no 返回 0... 所以default == no;
5. dependency-check (这个属性貌似在3.0里边有所改变)
String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE); bd.setDependencyCheck(getDependencyCheck(dependencyCheck));
这个在得到值之后,也是在getDependencyCheck方法中单独处理,返回的也是int值代表:
public int getDependencyCheck(String attValue) { String att = attValue; // 默认attValue 是 "" if (DEFAULT_VALUE.equals(att)) {// default att = this.defaults.getDependencyCheck(); // att == "" } if (DEPENDENCY_CHECK_ALL_ATTRIBUTE_VALUE.equals(att)) {// all return AbstractBeanDefinition.DEPENDENCY_CHECK_ALL; // 3 } else if (DEPENDENCY_CHECK_OBJECTS_ATTRIBUTE_VALUE.equals(att)) { // objects return AbstractBeanDefinition.DEPENDENCY_CHECK_OBJECTS; // 1 } else if (DEPENDENCY_CHECK_SIMPLE_ATTRIBUTE_VALUE.equals(att)) { // simple return AbstractBeanDefinition.DEPENDENCY_CHECK_SIMPLE;// 2 } else { return AbstractBeanDefinition.DEPENDENCY_CHECK_NONE; // 0 } }
6. depends-on
<strong> </strong>if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn,MULTI_VALUE_ATTRIBUTE_DELIMITERS)); }
依赖关系,通过代码就可以看出来,这个的值,在spring内部切割的时候,使用MULTI_VALUE_ATTRIBUTE_DELIMITERS切割,而MULTI_VALUE_ATTRIBUTE_DELIMITERS的值是“,; ”(逗号、分号、空格);
7. 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)); }
默认是default,用于指定自动装配时会不会考虑该bean,取值为 true/false;
8.