1. 程式人生 > >使用Spring實現屬性檔案給常量賦值

使用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>