[b]1.bean读取方式一:[/b]
Bean配置在内部是通过实习了BeanDefination接口的类实例来表现的,Bean的配置不仅存储了bean自己的信息,而其也体现了bean的依赖信息。对于任何同时实现了beanDefinationRegistery接口的BeanFantory类,你可以通过配置文件中读取Bean定义,通过PropertiesBeanDefinitionReader类就是一种方式。还又另一种方式,下次介绍。
[b]2.看PropertiesBeanDefinitionReader源代码:[/b]
public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader {..............................}
[b]主要方法:[/b]
[b]loadBeanDefinitions();加载bean属性定义从一个properties文件,这个文件资源被封装到一个带编码方式的资源,并按该编码方式解析文件,prefix是过滤的前缀,可以为空。返回取得的bean的数量[/b]
public int loadBeanDefinitions(EncodedResource encodedResource, String prefix) throws BeansException { Properties props = new Properties(); try { InputStream is = encodedResource.getResource().getInputStream(); try { if (encodedResource.getEncoding() != null) {//运用属性持久器[b](这里用的是:DefaultPropertiesPersister)[/b]以流的形式,并按制定的编码方式加载bean属性 getPropertiesPersister().load(props, new InputStreamReader(is, encodedResource.getEncoding())); } else {// getPropertiesPersister().load(props, is); } } finally {//关闭流 is.close(); }//调用下面介绍的另一个重要方法,去注册bean return registerBeanDefinitions(props, prefix, encodedResource.getResource().getDescription()); } catch (IOException ex) { throw new BeanDefinitionStoreException("Could not parse properties from " + encodedResource.getResource(), ex); } }
[b]registerBeanDefinitions();解析出bean的名字,让后调用注册方法,注册beanName到工厂,返回注册过的bean的数量[/b]
public int registerBeanDefinitions(Map map, String prefix, String resourceDescription) throws BeansException { if (prefix == null) { prefix = ""; } int beanCount = 0; for (Iterator it = map.keySet().iterator(); it.hasNext();) { Object key = it.next(); if (!(key instanceof String)) { throw new IllegalArgumentException("Illegal key [" + key + "]: only Strings allowed"); } String keyString = (String) key; if (keyString.startsWith(prefix)) { // Key is of form: prefix<name>.property String nameAndProperty = keyString.substring(prefix.length()); // Find dot before property name, ignoring dots in property keys. int sepIdx = -1; int propKeyIdx = nameAndProperty.indexOf(PropertyAccessor.PROPERTY_KEY_PREFIX); if (propKeyIdx != -1) { sepIdx = nameAndProperty.lastIndexOf(SEPARATOR, propKeyIdx); } else { sepIdx = nameAndProperty.lastIndexOf(SEPARATOR); } if (sepIdx != -1) { String beanName = nameAndProperty.substring(0, sepIdx); if (logger.isDebugEnabled()) { logger.debug("Found bean name '" + beanName + "'"); } if (!getBeanFactory().containsBeanDefinition(beanName)) { // If we haven't already registered it... registerBeanDefinition(beanName, map, prefix + beanName, resourceDescription); ++beanCount; } } else { // Ignore it: It wasn't a valid bean name and property, // although it did start with the required prefix. if (logger.isDebugEnabled()) { logger.debug("Invalid bean name and property [" + nameAndProperty + "]"); } } } } return beanCount; }
[b]registerBeanDefinition();得到bean的所有属性值,并加一前缀,并讲bean注册到工厂[/b]
protected void registerBeanDefinition(String beanName, Map map, String prefix, String resourceDescription) throws BeansException {//bean的属性 String className = null; String parent = null; boolean isAbstract = false; boolean singleton = true; boolean lazyInit = false; ConstructorArgumentValues cas = new ConstructorArgumentValues(); MutablePropertyValues pvs = new MutablePropertyValues(); for (Iterator it = map.entrySet().iterator(); it.hasNext();) { Map.Entry entry = (Map.Entry) it.next(); String key = StringUtils.trimWhitespace((String) entry.getKey()); if (key.startsWith(prefix + SEPARATOR)) { String property = key.substring(prefix.length() + SEPARATOR.length()); if (isClassKey(property)) { className = StringUtils.trimWhitespace((String) entry.getValue()); } else if (PARENT_KEY.equals(property)) { parent = StringUtils.trimWhitespace((String) entry.getValue()); } else if (ABSTRACT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); isAbstract = TRUE_VALUE.equals(val); } else if (SINGLETON_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); singleton = (val == null) || TRUE_VALUE.equals(val); } else if (LAZY_INIT_KEY.equals(property)) { String val = StringUtils.trimWhitespace((String) entry.getValue()); lazyInit = TRUE_VALUE.equals(val); } else if (property.startsWith(CONSTRUCTOR_ARG_PREFIX)) { if (property.endsWith(REF_SUFFIX)) { int index = Integer.parseInt(property.substring(1, property.length() - REF_SUFFIX.length())); cas.addIndexedArgumentValue(index, new RuntimeBeanReference(entry.getValue().toString())); } else { int index = Integer.parseInt(property.substring(1)); cas.addIndexedArgumentValue(index, readValue(entry)); } } else if (property.endsWith(REF_SUFFIX)) { // This isn't a real property, but a reference to another prototype // Extract property name: property is of form dog(ref) property = property.substring(0, property.length() - REF_SUFFIX.length()); String ref = StringUtils.trimWhitespace((String) entry.getValue()); // It doesn't matter if the referenced bean hasn't yet been registered: // this will ensure that the reference is resolved at runtime. Object val = new RuntimeBeanReference(ref); pvs.addPropertyValue(property, val); } else{ // It's a normal bean property. pvs.addPropertyValue(property, readValue(entry)); } } } if (logger.isDebugEnabled()) { logger.debug("Registering bean definition for bean name '" + beanName + "' with " + pvs); } // Just use default parent if we're not dealing with the parent itself, // and if there's no class name specified. The latter has to happen for // backwards compatibility reasons. if (parent == null && className == null && !beanName.equals(this.defaultParentBean)) { parent = this.defaultParentBean; } try {//这里用解析出的属性,构建一个beanDefination的基类实例 AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition( parent, className, getBeanClassLoader()); bd.setAbstract(isAbstract); bd.setSingleton(singleton); bd.setLazyInit(lazyInit); bd.setConstructorArgumentValues(cas); bd.setPropertyValues(pvs);//这里讲该bean注册到beanFantory getBeanFactory().registerBeanDefinition(beanName, bd); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(resourceDescription, beanName, className, err); } }
[code="java"][/code]