最近自己写了一个读取资源配置文件程序,顺带直接回顾了一下反射的知识。通过反射获取类、类对应的属性、类中的方法、设置属性值、执行方法。
网上大多数的获取资源文件中的配置是直接使用注解的,所以我这里特定整理了直接使用代码读取资源,这样有利用理解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