1. 程式人生 > >利用Java 動態代理,自定義註解 讀取配置檔案中的屬性值

利用Java 動態代理,自定義註解 讀取配置檔案中的屬性值

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 動態代理在實際工作中的應用 和實踐。