`

基于Properties文件读取Bean定义

阅读更多
1.bean读取方式一:
Bean配置在内部是通过实习了BeanDefination接口的类实例来表现的,Bean的配置不仅存储了bean自己的信息,而其也体现了bean的依赖信息。对于任何同时实现了beanDefinationRegistery接口的BeanFantory类,你可以通过配置文件中读取Bean定义,通过PropertiesBeanDefinitionReader类就是一种方式。还又另一种方式,下次介绍。
2.看PropertiesBeanDefinitionReader源代码:
public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader {
..............................
}

主要方法:
loadBeanDefinitions();加载bean属性定义从一个properties文件,这个文件资源被封装到一个带编码方式的资源,并按该编码方式解析文件,prefix是过滤的前缀,可以为空。返回取得的bean的数量
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);
		}
	}

registerBeanDefinitions();解析出bean的名字,让后调用注册方法,注册beanName到工厂,返回注册过的bean的数量
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;
	}

registerBeanDefinition();得到bean的所有属性值,并加一前缀,并讲bean注册到工厂
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);
		}
	}



  


  
分享到:
评论

相关推荐

    SSM 读取properties文件

    这是一个Spring的bean定义类,它允许我们从properties文件中加载和解析属性值,然后将这些值注入到其他bean的属性中。首先,我们需要创建一个properties文件,例如`application.properties`,并放入项目的类路径下...

    spring读取properties

    在Spring的配置文件中,首先需要定义一个`PropertyPlaceholderConfigurer` bean,这是Spring用来解析Properties文件并将其值注入到其他bean中的关键组件。如示例所示: ```xml &lt;bean id="propertyConfigurer" class...

    Spring 读取properties文件key+value方式.rar

    Spring框架提供了强大的属性配置管理,能够帮助开发者轻松地读取和使用properties文件中的key-value对。本教程将深入探讨如何在Spring中以不同的方式读取properties文件,以便更好地理解和应用这些配置。 首先,...

    加载properties配置文件的几种方法

    首先,在Spring的配置文件(如`applicationContext.xml`)中定义一个bean,然后指定properties文件的位置: ```xml &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt; ...

    Spring加载配置和读取多个Properties文件的讲解

    在上面的配置中,我们定义了一个`PropertyPlaceholderConfigurer`bean,并将三个 Properties 文件加载到容器中。这些文件分别是`demo-db.properties`、`demo-mq.properties`和`demo-remote.properties`。 在加载...

    Spring Bean 加载顺序 .

    Spring会首先读取这些配置源,将其转换为Bean定义。 2. **Bean定义注册**: 解析后的配置会被转化为BeanDefinition对象,包含Bean的类名、依赖、初始化方法等信息。这些BeanDefinition被注册到Spring的...

    Spring中配置和读取多个Properties文件的方式方法

    加载完配置文件后,Spring会自动处理Bean定义中的占位符`${...}`,将其替换为Properties文件中对应的值。例如,对于`MQJndiTemplate` Bean的配置,我们可以这样设置JNDI环境: ```xml &lt;bean id="MQJndiTemplate" ...

    详解SpringMVC加载配置Properties文件的几种方式

    在`jdbc.properties`文件中,我们可以定义如下内容: ```properties jdbc_driverClassName=com.mysql.jdbc.Driver jdbc_url=jdbc:mysql://localhost/testdb?useUnicode=true&characterEncoding=utf8 jdbc_username=...

    struts.properties文件详解

    Struts.properties 文件是 Struts2 框架的核心配置文件之一,它定义了框架的行为和各种默认设置。这个文件主要用于定制 Struts2 的工作环境,包括配置管理器、国际化、对象工厂、文件上传、请求映射等多个方面。下面...

    spring mvc 读取配置文件

    在Spring MVC框架中,配置文件是整个应用的核心组成部分,它定义了bean的创建、依赖关系以及各种服务的配置...熟练掌握配置文件的读取、bean的定义以及环境变量的处理,能够帮助开发者更好地控制和优化应用的运行行为。

    Bean-Message标签

    该标签允许开发者轻松地从资源文件中读取并显示预定义的消息文本,这对于创建多语言应用程序非常有用。 例如: ```xml &lt;bean:message key="welcome.title"/&gt; ``` 这里的 `key="welcome.title"` 指定了资源文件中的...

    引入多个properties时.txt

    这里`${driver}`和`${logLevel}`就是从`properties`文件中获取的值。 ### 三、解决引入多个`properties`文件时的问题 #### 3.1 属性覆盖问题 如果多个`properties`文件中定义了相同的属性,那么后加载的文件中的...

    使用xDoclet自动生成Spring的bean的配置文件

    然而,随着Spring的发展,Java配置(@Configuration)和基于注解的配置(@ComponentScan、@Autowired等)逐渐取代了xDoclet,因为它们提供了更直接、更灵活的bean定义方式。尽管如此,理解xDoclet的工作原理和使用...

    消息队列监听器无法注入bean的问题解决

    `system.properties`是系统属性文件,虽然在Spring中主要用的是`application.properties`或`application.yml`,但有可能开发者使用了自定义的方式来读取配置。检查其中是否有关于MQ或者bean的配置可能有助于解决问题...

    springboot_properties

    使用`messages.properties`文件可以实现国际化,通过`MessageSource`获取不同语言的文本。 9. **配置属性优先级** Spring Boot加载配置时遵循一定的顺序:命令行参数 &gt; `SPRING_APPLICATION_JSON` &gt; `@Property...

    spring bean 属性总结

    - **id属性**:是Bean在BeanFactory中的唯一标识符,用于通过BeanFactory获取Bean实例。例如,`&lt;bean id="myBean" class="com.example.MyClass"&gt;`。 - **name属性**:类似于`id`属性,但可以定义多个别名。例如,`...

    spring,配置文件从属性文件读取JDBC连接的相关参数

    一旦数据源bean被定义,我们就可以在其他bean中通过依赖注入来使用它,例如,创建一个`JdbcTemplate`或`JPA`相关的bean: ```xml &lt;!-- 使用JdbcTemplate --&gt; &lt;bean id="jdbcTemplate" class="org.springframework....

    Spring源码流程图

    Bean工厂提供了 BeanDefinitionReader 来读取Bean定义信息,并将其转换为BeanDefinition对象。然后,Bean工厂使用BeanDefinition对象来创建Bean实例,并将其注册到容器中。 Bean生命周期 Bean生命周期是指Bean从...

    struts-bean:message使用

    - 在这些文件中,定义键值对,例如`greeting=Hello` 和 `greeting=你好`。 2. **配置Struts** - 在`struts-config.xml`或`struts.properties`中,指定默认的语言环境和资源包位置。 3. **使用&lt;bean:message&gt;标签...

Global site tag (gtag.js) - Google Analytics