Java动态代理在一些中间件中经常用到,或者一些大型项目中都会用到。
这里顺带使用一下自定义注解方式,基于java 反射机制读取.properties格式文件。
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 动态代理在实际工作中的应用 和实践。