利用Java注解特性加载属性文件(properties)的值到Java类

Spring提供一个PropertyPlaceholderConfigurer类,可以读取配置文件,然后在Spring配置文件通过${Hibernate.dialect}这种方式注入到JavaBean中,有个不好的地方就是,要在代码中取的时候不是很方便.

现在我们可以通过Java注解特性加载属性文件(properties)的值到Java类里面,要实现现在说的这个功能,大体方案有如下:

1.定义一个注解类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD})
public @interface Config {
	
	String value() default "";

}


2.在需要加载属性的JavaBean的属性set方法上写注解,注解的参数就是key

@Component
public class JavaBean {
  private String name;
  private String address;
  public String getName() {
    return name;
  }
  @Config("com.test.JavaBean.name")
  public void setName(String name) {
    this.name = name;
  }
  public String getAddress() {
    return address;
  }
  public void setAddress(String address) {
    this.address = address;
  }
}



3.在Spring启动的时候,去读取属性文件,然后把值赋给JavaBean,这是实现这个功能的最关键的一步。

写一个类继承PropertyPlaceholderConfigurer类.然后在PropertyPlaceholderConfigurer初始化完成以后,获取加载的属性文件内容

public class CdpsnPropertyPlaceholderConfigurer extends
		PropertyPlaceholderConfigurer {
	
	private Properties props;

	@Override
	protected void processProperties(
			ConfigurableListableBeanFactory beanFactoryToProcess,
			Properties props) throws BeansException {
		super.processProperties(beanFactoryToProcess, props);
		this.props=props;
	}

	public Object getProperty(String key) {
		return props.getProperty(key);
	}
	
}



写一个JavaBean实现BeanPostProcessor接口,这个Bean有个属性,它指向属性文件路径,在这个Bean初始化的时候读取属性文件内容

@Component
public class ConfigAnnotationBeanPostProcessor extends
		InstantiationAwareBeanPostProcessorAdapter {
	@Autowired
	private CdpsnPropertyPlaceholderConfigurer propertyConfigurer;
	//创建简单类型转换器
	private SimpleTypeConverter typeConverter = new SimpleTypeConverter();

	@Override
	public boolean postProcessAfterInstantiation(final Object bean, String beanName)
			throws BeansException {
	
	ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
		         public void doWith(Field field) throws IllegalArgumentException, 
		                IllegalAccessException {
		             Config cfg = field.getAnnotation(Config.class);
		             if (cfg != null) {
		                if (Modifier.isStatic(field.getModifiers())) {
		                   throw new IllegalStateException("@Config annotation is not supported"+ 
		                            "on static fields");
		                }
		 
		             //如果开发者没有设置@Config的 value,则使用变量域的名称作为键查找配置资源
		             String key = cfg.value().length() <= 0 ? field.getName() : cfg.value();
		             Object value = propertyConfigurer.getProperty(key);
	 
		             if (value != null) {
		               //转换配置值成其它非String类型
		                Object _value = typeConverter.convertIfNecessary(value, field.getType());
		                //使变量域可用,并且转换后的配置值注入其中
		                ReflectionUtils.makeAccessible(field);
		                field.set(bean, _value);
		             }
		          }
		       }
		   });
	
		    //通常情况下返回true即可
		    return true;
	}

}



配置文件

<!-- 属性文件配置路径 -->
	<bean id="propertyConfigurer"
		class="com.test.config.CdpsnPropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:/config/config.properties</value>
				<value>classpath:/config/jdbc.properties</value>
			</list>
		</property>
	</bean>



ps:之所以要继承PropertyPlaceholderConfigurer类,还有一个原因就是,原来通过${}注入值的方式还可以用

你可能感兴趣的:(java,spring,properties)