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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章