利用Java 動態代理,自定義註解 讀取配置檔案中的屬性值
阿新 • • 發佈:2019-01-09
Java動態代理在一些中介軟體中經常用到,或者一些大型專案中都會用到。
這裡順帶使用一下自定義註解方式,基於java 反射機制讀取.properties格式檔案。
demo的大致內容包含以下:
1.配置檔案:config.properties
url=http://www.hrsstd.com
password= root
username= zhanghuilong
port = 8080
isOpen = true
2.自定義註解類
註解中的原生標籤具體含義可以自行了解
/** * @author zhanghuilong * @desc 自定義註解,讀取配置檔案內容 * @since 2019/01/02 */ @Target({ ElementType.FIELD, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ReadConf { /** * read config.properties context eg: key = value * @return */ String value(); }
3.demo介面定義
/** * @author zhanghuilong * @desc 配置中心 * @since 2019/01/02 */ public interface HrsConfigService { @ReadConf(value = "url") String getUrl(); @ReadConf("password") String getPwd(); @ReadConf("username") String getUserName(); @ReadConf("port") Integer getPort(); @ReadConf("isOpen") Boolean getOff(); }
4.動態代理核心實現
invocationHandler的實現
/** * @author zhanghuilong * @desc 動態代理具體實現方法 * @since 2019/01/02 */ public class PropertyInvocationHandler implements InvocationHandler { private Properties properties; public PropertyInvocationHandler(Properties properties) { this.properties = properties; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(" 呼叫 method = [" + method.getName() +"]"); ReadConf readConf = method.getAnnotation(ReadConf.class); if (readConf == null){ return null; } String value = readConf.value(); String property = properties.getProperty(value); if (StringUtils.isEmpty(property)){ return null; } Class<?> returnClass = method.getReturnType(); // 基本原始型別,這裡只寫了部分型別,滿足當前demo介面返回值型別,如遇專案有多重型別,可以新增補全所以型別 if (returnClass.isPrimitive()){ if (returnClass.equals(int.class)){ return Integer.valueOf(property); } else if (returnClass.equals(long.class)){ return (Long.valueOf(property));} else if (returnClass.equals(double.class)) {return (Double.valueOf(property));} else if (returnClass.equals(float.class)) { return (Float.valueOf(property)); } else if (returnClass.equals(boolean.class)) { return (Boolean.valueOf(property));} }else { if (returnClass.equals(Integer.class)){ return Integer.valueOf(property); }else if (returnClass.equals(String.class)){ return String.valueOf(property); }else if (returnClass.equals(Boolean.class)){ return Boolean.valueOf(property); } } return property; } }
5.讀取配置的通用工廠方法
/**
* @author zhanghuilong
* @desc 讀取配置工廠方法
* @since 2019/01/02
*/
public class HrsConfigFactory {
public HrsConfigFactory() {
}
/**
* 讀取方法
* @param inputStream
* @return
*/
public static HrsConfigService readProperties(final InputStream inputStream){
final Properties properties = new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
System.out.println("load inputStream error ");
return null;
}
// java 代理機制
return (HrsConfigService)Proxy
.newProxyInstance(HrsConfigService.class.getClassLoader(), new Class[] { HrsConfigService.class },
new PropertyInvocationHandler(properties));
}
}
6.demo 的測試執行類main方法
/**
* @author zhanghuilong
* @desc 動態代理+自定義註解
* @since 2019/01/02
*/
public class DemoTest {
public static void main(String[] args) {
try {
// 檔案地址可以直接copypath
InputStream fileInputStream = new FileInputStream("/Users/zhanghuilong/demo/config.properties");
HrsConfigService configService = HrsConfigFactory.readProperties(fileInputStream);
if (configService == null){
return;
}
Integer port = configService.getPort();
String url = configService.getUrl();
String userName = configService.getUserName();
String pwd = configService.getPwd();
Boolean off = configService.getOff();
String format = String.format("讀取配置資訊,url: %s, username: %s, password: %s, port :%s, 開關:%s",
url, userName, pwd, port, off);
System.out.println( format );
} catch (FileNotFoundException e) {
System.out.println("檔案不存在");
}
}
}
輸出:
呼叫 method = [getPort]
呼叫 method = [getUrl]
呼叫 method = [getUserName]
呼叫 method = [getPwd]
呼叫 method = [getOff]
讀取配置資訊,url: http://www.hrsstd.com, username: zhanghuilong, password: root, port :8080, 開關:true
本文主要想簡單說明下 java 動態代理在實際工作中的應用 和實踐。