利用Java的动态代理模式动态加载属性

在我看Stackoverflow的时候,我碰到了这样一个有趣的问题:如何将Java属性文件Properties File绑定到Java接口。这个想法简单却有用!

当我们想在应用中使用常量的时候,我们只需简单地用一下loginConstants.appDescription().我们的应用框架会为这个接口创建一个动态代理。我们所要做的仅仅是调用这个方法,得到默认值或从属性文件中得到值。
基本上是这样做:你创建一个带有相关方法的接口,然后用@Key和@DefaultStringValue注释这些方法。
免责声明:不能用于生产环境。代码仅供参考。下面代码还需优化。

下面是代码样本。

package net.viralpatel;

import net.viralpatel.annotations.DefaultStringValue;
import net.viralpatel.annotations.Key;

interface LoginConstants extends Constants {
	   @DefaultStringValue("Wellcome to my super app")
	   @Key("appDescription")
	   String appDescription();

	   @DefaultStringValue("Ok")
	   @Key("okButtonLabel")
	   String okButtonLabel();
}

public class Main {
	public static void main(String[] args) {
		LoginConstants constants = DynamicProperty.create(LoginConstants.class);
		System.out.println(constants.appDescription());
		System.out.println(constants.okButtonLabel());
	}
}
输出:

Wellcome to my super app
This is OK

一下是用Java反射实现的动态代理代码,能起到神奇的作用。

package net.viralpatel.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Key {
	public String value();
}

package net.viralpatel.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultStringValue {
	public String value();
}

package net.viralpatel;

import java.lang.reflect.Proxy;

public class DynamicProperty {
	
	public static <T extends Constants> T  create(Class<T> clazz) {
		
		T object = (T) Proxy.newProxyInstance(clazz
				.getClassLoader(), new Class[] { clazz },
				new Handler(clazz));  
		
		return object;
		
	}
}

package net.viralpatel;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import net.viralpatel.annotations.DefaultStringValue;
import net.viralpatel.annotations.Key;

public class Handler implements InvocationHandler {
	
	Object obj;

	public Handler(Object obj) {
		this.obj = obj;
	}
	
	public Object invoke(Object proxy, Method m, Object[] args)
			throws Throwable {
		String key = null;
		String defaultValue = null;
		try {

			Annotation[] annotations = m.getAnnotations();
			for (Annotation annotation : annotations) {
				if (annotation instanceof Key) {
					key = ((Key)annotation).value();
				} else if (annotation instanceof DefaultStringValue) {
					defaultValue = ((DefaultStringValue)annotation).value();
				}
			}

			String ret = PropertyLoader.get(key);
			return (null == ret) ? defaultValue : ret;
			
			// result = m.invoke(obj, args);

		} catch (Exception e) {
			// We could also put some code here if we want to do
			// anything special in case an Exception is thrown from
			// the inside of invoked method.
			throw e;
		}
	}
}

package net.viralpatel;

public interface Constants {
	//marker
}

package net.viralpatel;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class PropertyLoader {
	private static Properties prop = null;

	public static String get(String key) {
		if (null == prop) {
			init();
		}
		return (String) prop.get(key);
	}

	private static void init() {
		prop = new Properties();
		InputStream in = Properties.class
				.getResourceAsStream("/net/viralpatel/config.properties");
		try {
			prop.load(in);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

原文: http://viralpatel.net/blogs/dynamic-property-loader-using-java-dynamic-proxy-pattern/

源代码:http://pan.baidu.com/share/link?shareid=553186681&uk=3878681452

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值