Java 反射调用
1. 反射定义
是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
2.反射用途
在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。
3. RPC
调用
java远程调用,服务端反序列化请求数据后,根据全路径类名、方法名、参数列表,解析并反射调用服务端接口对外提供服务。
4. Gateway
的实现
为反射调用的扩展实现,不区分客户端实现方式,根据请求信息,反射处理后返回结果。
5. 示例代码
@Service
public class MethodInvokeJob implements SimpleJobProcessor {
private static final Logger logger = LoggerFactory.getLogger(MethodInvokeJob.class);
private static List<String> constantKeys = Arrays.asList("boolean", "char", "int", "byte", "short", "long", "float", "double", "java.lang.String");
private static List<String> constantValues = Arrays.asList("java.lang.Boolean", "java.lang.Character", "java.lang.Integer", "java.lang.Byte", "java.lang.Short", "java.lang.Long", "java.lang.Float", "java.lang.Double", "java.lang.String");
@Autowired
private ApplicationContext applicationContext;
@Override
public void process(JobContext context) throws Exception {
logger.info("Start Execute Task:" + this.getClass().getSimpleName() + " -> " + context.getParameter());
Map<String, Object> parameters = (Map<String, Object>) JSON.parse(context.getParameter());
executeInvoke(parameters);
logger.info("End Execute Task:" + this.getClass().getSimpleName() + " -> " + context.getParameter());
}
/**
* 执行反射操作,调用指定方法
*
* @param parameters
*/
private void executeInvoke(Map<String, Object> parameters) {
String className = String.valueOf(parameters.get("className"));
String method = String.valueOf(parameters.get("methodName"));
Map<String, Object> params = (Map<String, Object>) JSON.parse(String.valueOf(parameters.get("param")));
try {
Class<?> aClass = Class.forName(className);
Object instance = applicationContext.getBean(aClass);
Method[] methods = Class.forName(className).getDeclaredMethods();
Object ret = null;
for (int i = 0; i < methods.length; i++) {
if (method.equals(methods[i].getName()) && methods[i].getParameterCount() == params.size()) {
logger.info("开始执行反射操作: className {}, method {}, params {}", className, method, parameters.get("param"));
methods[i].setAccessible(true);
if (0 == params.size()){
ret = methods[i].invoke(instance);
}else {
List<Object> paramList = new ArrayList<>();
Class<?>[] paramsType = methods[i].getParameterTypes();
for (int j = 0; j < params.size(); j++) {
Object param = JSON.parseObject(String.valueOf(parameters.get("param" + j)), paramsType[j]);
paramList.add(param);
}
ret = methods[i].invoke(instance, paramList.toArray());
}
}
logger.info("执行反射操作完成: {}", ret);
}
} catch (Exception e) {
logger.error("执行反射调用失败->{}", e);
}
}
public void invoke(Map<String, Object> parameters) {
String className = String.valueOf(parameters.get("className"));
String method = String.valueOf(parameters.get("methodName"));
List<Object> params = (List<Object>) JSON.parse(String.valueOf(parameters.get("param")));
try {
Class<?> aClass = Class.forName(className);
Object instance = aClass.newInstance();
Method[] methods = Class.forName(className).getDeclaredMethods();
Object ret = null;
for (int i = 0; i < methods.length; i++) {
if (method.equals(methods[i].getName()) && methods[i].getParameterCount() == params.size()) {
logger.info("开始执行反射操作: className {}, method {}, params {}", className, method, parameters.get("param"));
methods[i].setAccessible(true);
if (0 == params.size()){
ret = methods[i].invoke(instance);
}else {
List<Object> paramList = new ArrayList<>();
Class<?>[] paramsType = methods[i].getParameterTypes();
for (int j = 0; j < paramsType.length; j++) {
if (constantKeys.contains(paramsType[j].getName())){
int index = constantKeys.indexOf(paramsType[j].getName());
String decodeType = constantValues.get(index);
Class<?> clazz = Class.forName(decodeType);
paramList.add(clazz.cast(params.get(j)));
}else {
paramList.add(JSON.parseObject(String.valueOf(params.get(j)), Class.forName(paramsType[j].getName())));
}
}
methods[i].invoke(instance, paramList.toArray());
}
}
logger.info("执行反射操作完成");
}
} catch (Exception e) {
logger.error("执行反射调用失败->{}", e);
}
}
}