使用Spring实现属性文件给常量赋值

简介:

测试代码如下;

 

package com.yanek.ioc;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-base.xml"})
public class MyTest3 {

	@Test
	public void test() {

		System.out.println("CHARSET:"+com.yanek.util.ConfigConstants.CHARSET);
		System.out.println("CONNECTTIMEOUT:"+com.yanek.util.ConfigConstants.CONNECTTIMEOUT);
		System.out.println("READTIMEOUT:"+com.yanek.util.ConfigConstants.READTIMEOUT);
	}

}

 

测试输出如下:

 

CHARSET:UTF-8
CONNECTTIMEOUT:1000
READTIMEOUT:5000

 


核心类:

package com.yanek.util;

import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

/**
 * 自定义PropertyPlaceholderConfigurer返回properties内容
 */ 

public class CustomizedPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
	/**
	 * 属性前缀,可以使用表达式${}。如果使用表达式,表示从属性文件中的字段读取。
	 * 如果为空,表示不使用前缀。
	 */
	private String prefix;
	
	/**
	 * 需要注入的常量类名数组
	 */
	private String[] configureClasses;

	@SuppressWarnings("unchecked")
	protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
			throws BeansException {
		super.processProperties(beanFactoryToProcess, props);

		if (configureClasses == null) return;
		
		String prefixValue = null;
		if (prefix != null && !prefix.isEmpty()){
			// 如果前缀是表达式,需要从属性中读取
			Pattern p = Pattern.compile("\\$\\{(.*)\\}");
			Matcher matcher = p.matcher(prefix);
			prefixValue = prefix;
			if (matcher.find()) {
				String prefixKey = matcher.group(1);
				prefixValue = props.getProperty(prefixKey);
			}	
		}

		// 遍历多个常量类
		for (int i = 0; i < configureClasses.length; i++) {
			Class c = null;
			try {
				c = Class.forName(configureClasses[i]);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
				continue;
			}
			
			Field[] fields = c.getFields();

			// 遍历属性列表,注入到常量字段中
			for (Enumeration<?> k = props.propertyNames(); k.hasMoreElements();) {
				String key = (String) k.nextElement();

				// 遍历常量字段数组,找到与属性对应的常量字段
				for (int j = 0; fields != null && j < fields.length; j++) {
					// 取出字段名称,如果有前缀,需要加上前缀
					String keyStr = fields[j].getName();
					if (prefixValue != null && !prefixValue.isEmpty())
						keyStr = prefixValue + "." + fields[j].getName();

					// 判断常量字段是否有属性匹配,不区分大小写。
					if (keyStr.equalsIgnoreCase(key)) {
						// 从属性中取出字段值,并存到字段中
						String value = props.getProperty(key);
						if (value != null) {
							value = value.trim();
							// fields[j].setAccessible(true);
							try {
								if (Integer.TYPE.equals(fields[j].getType())) {
									fields[j].setInt(null, Integer.parseInt(value));
								} else if (Long.TYPE.equals(fields[j].getType())) {
									fields[j].setLong(null, Long.parseLong(value));
								} else if (Short.TYPE.equals(fields[j].getType())) {
									fields[j].setShort(null, Short.parseShort(value));
								} else if (Double.TYPE.equals(fields[j].getType())) {
									fields[j].setDouble(null, Double.parseDouble(value));
								} else if (Float.TYPE.equals(fields[j].getType())) {
									fields[j].setFloat(null, Float.parseFloat(value));
								} else if (Boolean.TYPE.equals(fields[j].getType())) {
									fields[j].setBoolean(null, Boolean.parseBoolean(value));
								} else {
									fields[j].set(null, value);
								}
							} catch (IllegalArgumentException e) {
								e.printStackTrace();
							} catch (IllegalAccessException e) {
								e.printStackTrace();
							}

						}
						break;
					}
				}
			}
		}

	}

	public String getPrefix() {
		return prefix;
	}

	public void setPrefix(String prefix) {
		this.prefix = prefix;
	}

	public String[] getConfigureClasses() {
		return configureClasses;
	}

	public void setConfigureClasses(String[] configureClasses) {
		this.configureClasses = (configureClasses != null)? configureClasses.clone() : null;
	}
	
	public void setConfigureClass(String configureClass) {
		this.configureClasses = new String[] {configureClass};
	}
}


 

package com.yanek.util;

public class ConfigConstants {
	
	
	public static int CONNECTTIMEOUT = 0;
	public static int READTIMEOUT = 0;
	public static String CHARSET = "";

}


属性文件:application.properties

CONNECTTIMEOUT=1000
READTIMEOUT=5000
CHARSET=UTF-8


 spring配置文件:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
		http://www.springframework.org/schema/context 
 		http://www.springframework.org/schema/context/spring-context-2.5.xsd"
	default-autowire="byName" default-lazy-init="false">
	
	<!-- 从properties文件加载配置信息 -->
	<bean id="propertyPlaceholderConfigurer"
		class="com.yanek.util.CustomizedPropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:application.properties</value>
			</list>
		</property>
		<property name="configureClasses">
			<list>
				<value>com.yanek.util.ConfigConstants</value>
			</list>
		</property>		
	</bean>
	
	
</beans>


 

目录
相关文章
|
8天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
28 2
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
4月前
|
Java 测试技术 数据库
Spring Boot中的项目属性配置
本节课主要讲解了 Spring Boot 中如何在业务代码中读取相关配置,包括单一配置和多个配置项,在微服务中,这种情况非常常见,往往会有很多其他微服务需要调用,所以封装一个配置类来接收这些配置是个很好的处理方式。除此之外,例如数据库相关的连接参数等等,也可以放到一个配置类中,其他遇到类似的场景,都可以这么处理。最后介绍了开发环境和生产环境配置的快速切换方式,省去了项目部署时,诸多配置信息的修改。
|
5月前
|
XML druid Java
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
Spring5系列学习文章分享---第二篇(IOC的bean管理factory+Bean作用域与生命周期+自动装配+基于注解管理+外部属性管理之druid)
62 0
|
1月前
|
存储 前端开发 Java
Spring Boot 集成 MinIO 与 KKFile 实现文件预览功能
本文详细介绍如何在Spring Boot项目中集成MinIO对象存储系统与KKFileView文件预览工具,实现文件上传及在线预览功能。首先搭建MinIO服务器,并在Spring Boot中配置MinIO SDK进行文件管理;接着通过KKFileView提供文件预览服务,最终实现文档管理系统的高效文件处理能力。
278 11
|
1月前
|
Java Maven Spring
用Spring导致的无法运行Java文件的问题的解决方案
本文提供了解决在IntelliJ IDEA社区版中使用Spring Initializr插件创建Spring项目后,Java文件无法运行的问题的方法,主要是通过加载Maven项目来解决。
71 0
|
3月前
|
Java Spring 开发者
Spring 框架配置属性绑定大比拼:@Value 与 @ConfigurationProperties,谁才是真正的王者?
【8月更文挑战第31天】Spring 框架提供 `@Value` 和 `@ConfigurationProperties` 两种配置属性绑定方式。`@Value` 简单直接,适用于简单场景,但处理复杂配置时略显不足。`@ConfigurationProperties` 则以类级别绑定配置,简化代码并更好组织配置信息。本文通过示例对比两者特点,帮助开发者根据具体需求选择合适的绑定方式,实现高效且易维护的配置管理。
51 0
|
3月前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
44 0
|
3月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
3月前
|
Java Linux C++
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
【Azure 应用服务】App Service For Linux 部署Java Spring Boot应用后,查看日志文件时的疑惑
下一篇
无影云桌面