Java 读取配置文件的注解

在Java开发中,我们经常需要读取配置文件来获取一些运行时的参数或者配置信息。而使用注解是一种简洁、高效的方式来读取配置文件。本文将介绍如何使用注解来读取配置文件,并给出相应的代码示例。

什么是配置文件

首先,我们需要了解什么是配置文件。在Java中,配置文件是一种用于存储程序运行时的参数或配置信息的文件。常见的配置文件类型有.properties、.xml、.json等。

配置文件通常采用键值对的形式来存储配置信息,如:

# config.properties
server.port=8080
server.host=127.0.0.1
database.url=jdbc:mysql://localhost:3306/test

上述配置文件中定义了一个Web服务器的端口号、主机地址以及数据库连接字符串。我们可以使用注解来读取这些配置信息,并在程序中使用。

使用注解读取配置文件

接下来我们介绍如何使用注解来读取配置文件。首先,我们需要定义一个注解类,用来标识需要读取配置文件的字段或方法。示例代码如下:

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

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ConfigValue {
    String value() default "";
}

上述代码定义了一个名为ConfigValue的注解类,用来标识需要读取配置文件的字段或方法。@Target注解指定了该注解可以用于字段和方法上,@Retention注解指定了该注解的生命周期为运行时。

接下来,我们可以在需要读取配置文件的字段或方法上使用@ConfigValue注解。示例代码如下:

public class AppConfig {
    @ConfigValue("server.port")
    private int port;
    
    @ConfigValue("server.host")
    private String host;
    
    @ConfigValue("database.url")
    public String databaseUrl;
    
    // getters and setters
}

上述代码中,我们使用@ConfigValue注解标识了porthostdatabaseUrl字段。注解的值是配置文件中对应的键名。

接下来,我们需要编写一个配置文件读取的工具类。示例代码如下:

import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

public class ConfigReader {
    public static void readConfig(Object obj, String configFile) {
        Properties props = new Properties();
        
        try (FileInputStream fis = new FileInputStream(configFile)) {
            props.load(fis);
            
            Class<?> clazz = obj.getClass();
            
            for (Field field : clazz.getDeclaredFields()) {
                if (field.isAnnotationPresent(ConfigValue.class)) {
                    ConfigValue annotation = field.getAnnotation(ConfigValue.class);
                    String key = annotation.value();
                    String value = props.getProperty(key);
                    
                    field.setAccessible(true);
                    field.set(obj, castValue(field.getType(), value));
                }
            }
            
            for (Method method : clazz.getDeclaredMethods()) {
                if (method.isAnnotationPresent(ConfigValue.class)) {
                    ConfigValue annotation = method.getAnnotation(ConfigValue.class);
                    String key = annotation.value();
                    String value = props.getProperty(key);
                    
                    method.setAccessible(true);
                    method.invoke(obj, castValue(method.getParameterTypes()[0], value));
                }
            }
        } catch (IOException | ReflectiveOperationException e) {
            e.printStackTrace();
        }
    }
    
    private static Object castValue(Class<?> type, String value) {
        if (type.equals(int.class) || type.equals(Integer.class)) {
            return Integer.parseInt(value);
        } else if (type.equals(long.class) || type.equals(Long.class)) {
            return Long.parseLong(value);
        } else if (type.equals(float.class) || type.equals(Float.class)) {
            return Float.parseFloat(value);
        } else if (type.equals(double.class) || type.equals(Double.class)) {
            return Double.parseDouble(value);
        } else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
            return Boolean.parseBoolean(value);
        } else {
            return value;
        }
    }
}

上述代码中,我们编写了一个ConfigReader类,其中的readConfig方法用于读取配置文件并将配置值设置到对应的字段或方法中。

readConfig方法中,我们首先加载配置文件并解析为Properties对象。然后遍历目标类的字段和方法,通过判断是否带有@ConfigValue注解