Java中的反射以及在spring下读取resources目录下的文件(不使用注解)

最近自己写了一个读取资源配置文件程序,顺带直接回顾了一下反射的知识。通过反射获取类、类对应的属性、类中的方法、设置属性值、执行方法。

网上大多数的获取资源文件中的配置是直接使用注解的,所以我这里特定整理了直接使用代码读取资源,这样有利用理解spring中对资源的管理。

由于习惯了springboot中不用自己整理依赖的版本,所以,直接就使用了springboot建立的工程。

对其中用到的内容都进行了封装:

封装的类及测试方法。(直接在main方法中测试的,没有用单元测试)

package cn.lframe.parsingconfiguration.reflection_study;


import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * 首先读取资源配置文件(config.properties)中的内容。
 * 通过反射获取类、类对应的属性、类中的方法、设置属性值、执行方法。
 * 每一个方法都进行了封装。
 * @author Lframe
 * @create2018 -05 -26 -8:16
 */
@Slf4j
public class TestReflect {

    public static void main(String[] args) throws Exception {
        String name = getPropertiesValue("config.properties", "name");
        String age = getPropertiesValue("config.properties", "age");
        String className = getPropertiesValue("config.properties", "class");
        String methodName = getPropertiesValue("config.properties", "method");
//        People people = (People) getObject(className);
        String returnValue = (String) executeMethod( className, methodName);
        log.info("【返回值】:{}", returnValue);
        Object o = setField(className, "age", 18);
        log.info("【结果:】{}", o);
    }

    /**
     * 为对应的域设置响应的值。
     * @param className 完整的类名(包括包名)
     * @param fieldName 实例域的域名
     * @param propertyValue 实例域对应的值
     * @return 该域所在类的对象
     * @throws Exception
     */
    private static Object setField(String className, String fieldName, Object propertyValue) throws Exception {
        Field field = getDeclaredField(className, fieldName);
        field.setAccessible(true);
        Object object = getObject(className);
        field.set(object, propertyValue);
        return object;
    }

    /**
     * 通过该方法返回对应类名、实例域名对应的方法
     * @param className 完整的类名(包括包名)
     * @param fieldName 对应实例域的名字
     * @return 返回实例域对象
     * @throws Exception
     */
    private static Field getDeclaredField(String className, String fieldName) throws Exception {
        Class clazz = Class.forName(className);
        return clazz.getDeclaredField(fieldName);
    }

    /**
     *通过类名、方法名、对应方法名的方法的参数去执行对应的方法
     * @param className  完整的类名(包括包名)
     * @param methodName 相应的方法名
     * @param args 方法参数
     * @return 方法的执行结果
     * @throws Exception
     */
    private static Object executeMethod( String className, String methodName, Object... args) throws Exception {
        Object object= getObject(className);
        Method method = getMethod(className, methodName);
        return method.invoke(object, args);
    }

    /**
     * 通过反射获取类对象
     * @param className 完整的类名(包括包名)
     * @return 返回一个该类名的对应的对象
     * @throws Exception
     */
    private static Class getClass(String className) throws Exception {
        return Class.forName(className);
    }

    /**
     * 返回该类名对应的实例对象
     * @param className 完整的类名(包括包名)
     * @return 对象 Object
     * @throws Exception
     */
    private static Object getObject(String className) throws Exception {
        Class clazz = getClass(className);
        Constructor constructor = clazz.getConstructor();
        return constructor.newInstance();
    }


    /**
     * 获取类对应的对象的方法
     * @param className 完整的类名(包括包名)
     * @param methodName 要获取的方法的对应的名称
     * @return Method
     * @throws Exception
     */
    private static Method getMethod(String className, String methodName) throws Exception {
        Class clazz = getClass(className);
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                return method;
            }
        }
        throw new NoSuchMethodException();

    }

    /**
     * 通过路径获取资源(Resource)
     *
     * @param location 相对于resources的位置
     * @return Resource 它是spring中所有内容的总称。
     * @throws IOException 如果获取不到,将抛出该异常
     */
    private static Resource getResource(String location) throws IOException {
        ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
        return resourcePatternResolver.getResource(location);
    }

    /**
     * 通过location获取properties类型的文件
     *
     * @param location properties文件相对于resources目录下的位置
     * @return Properties 直接返回可以使用的properties文件
     * @throws IOException
     */
    private static Properties loadFileReader(String location) throws IOException {
        Resource resource = getResource(location);
        File file = resource.getFile();
        FileReader fileReader = new FileReader(file);
        Properties properties = new Properties();
        properties.load(fileReader);
        return properties;
    }

    /**
     * 获取properties文件的属性值
     *
     * @param location properties文件相对于resources目录下的位置
     * @param key 资源文件的key
     * @return value 返回资源文件的值
     * @throws IOException
     */
    public static String getPropertiesValue(String location, String key) throws IOException {
        Properties properties = loadFileReader(location);
        return properties.getProperty(key);
    }


}

资源文件:config.properties
放在resources目录下,默认在springboot中,不允许直接通过绝对路径访问资源,只能通过相对路径访问resources目录下的资源文件。

name=lframe
age=22
class=cn.lframe.parsingconfiguration.bean.People
method=say

你可能感兴趣的:(Spring)