需求:
避免编写重复的代码,如何把下面的两个需求抽取成公共逻辑;
1. 调用其他方法时打印被调用方法的路径、入参、以及执行耗时情况;
2. 调用方法遇到异常时,灵活控制是否要捕获异常或者抛出异常;
实现思路
- 使用函数式编程;
1.1. 创建一个接口(用来获取函数真实的调用路径和方法)
package com.xxx.utils.function;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
/**
*
*/
public interface SerializedLambdaFunction extends Serializable {
/**
* 这个方法返回的SerializedLambda是重点
* @return
* @throws Exception
*/
default SerializedLambda getSerializedLambda() throws Exception {
//writeReplace改了好像会报异常
Method write = this.getClass().getDeclaredMethod("writeReplace");
write.setAccessible(true);
return (SerializedLambda) write.invoke(this);
}
/**
* 获取函数真实调用的实现类名
* @return
*/
default String getImplClass() {
try {
return getSerializedLambda().getImplClass();
} catch (Exception e) {
return null;
}
}
/**
* 获取函数真实调用的实现方法名
* @return
*/
default String getImplMethodName() {
try {
return getSerializedLambda().getImplMethodName();
} catch (Exception e) {
return null;
}
}
/**
* 获取函数真实调用的类名#方法名
* @return
*/
default String getClassAndMethodName() {
try {
return getImplClass() + "#" + getImplMethodName();
} catch (Exception e) {
return null;
}
}
}
1.2. 创建一个函数接口(继承SerializedLambdaFunction)
下面是只接收一个参数并且有返回值的函数接口,如果要编写多个参数的函数接口只需要在<>泛型中和apply方法中添加泛型即可;
package com.xxx.utils.function;
/**
* 接收一个参数并返回结果的函数
* 函数方法是 {@link #apply(Object)}
*
* @param <T> 第一个参数
* @param <R> 返回结果
*/
@FunctionalInterface
public interface MonoFunction<T, R> extends SerializedLambdaFunction {
/**
* 使用指定的参数调用该方法
*
* @param t 第一个参数
* @return 返回结果