实际上,您可以使用代理模式构建这样的框架或模板。在这里,我解释了如何使用动态代理模式来做到这一点。这个想法是,
- 编写一个代理管理器来按需获取 API 的记录器和回放器代理!
- 编写一个包装类来存储您收集的信息,并实现该包装类的方法
hashCode
和方法,以便从类似的数据结构equals
中进行有效查找。Map
- 最后使用记录器代理进行记录和回放代理用于回放目的。
录音机的工作原理:
- 调用真正的 API
- 收集调用信息
- 在预期的持久性上下文中持久化数据
回放器的工作原理:
- 收集方法信息(方法名、参数)
- 如果收集的信息与之前记录的信息匹配,则返回之前收集的返回值。
- 如果返回值不匹配,则保留收集到的信息(如您所愿)。
现在,让我们看一下实现。如果您的 APIMyApi
如下所示:
public interface MyApi {
public String getMySpouse(String myName);
public int getMyAge(String myName);
...
}
现在我们将记录并重放public String getMySpouse(String myName)
. 为此,我们可以使用一个类来存储调用信息,如下所示:
public class RecordedInformation {
private String methodName;
private Object[] args;
private Object returnValue;
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Object getReturnValue() {
return returnType;
}
public void setReturnValue(Object returnValue) {
this.returnValue = returnValue;
}
@Override
public int hashCode() {
return super.hashCode(); //change your implementation as you like!
}
@Override
public boolean equals(Object obj) {
return super.equals(obj); //change your implementation as you like!
}
}
现在这里是主要部分,RecordReplyManager
. 这RecordReplyManager
为您提供API 的代理对象,具体取决于您录制或重播的需要。
public class RecordReplyManager implements java.lang.reflect.InvocationHandler {
private Object objOfApi;
private boolean isForRecording;
public static Object newInstance(Object obj, boolean isForRecording) {
return java.lang.reflect.Proxy.newProxyInstance(
obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
new RecordReplyManager(obj, isForRecording));
}
private RecordReplyManager(Object obj, boolean isForRecording) {
this.objOfApi = obj;
this.isForRecording = isForRecording;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
if (isForRecording) {
try {
System.out.println("recording...");
System.out.println("method name: " + method.getName());
System.out.print("method arguments:");
for (Object arg : args) {
System.out.print(" " + arg);
}
System.out.println();
result = method.invoke(objOfApi, args);
System.out.println("result: " + result);
RecordedInformation recordedInformation = new RecordedInformation();
recordedInformation.setMethodName(method.getName());
recordedInformation.setArgs(args);
recordedInformation.setReturnValue(result);
//persist your information
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
} finally {
// do nothing
}
return result;
} else {
try {
System.out.println("replying...");
System.out.println("method name: " + method.getName());
System.out.print("method arguments:");
for (Object arg : args) {
System.out.print(" " + arg);
}
RecordedInformation recordedInformation = new RecordedInformation();
recordedInformation.setMethodName(method.getName());
recordedInformation.setArgs(args);
//if your invocation information (this RecordedInformation) is found in the previously collected map, then return the returnValue from that RecordedInformation.
//if corresponding RecordedInformation does not exists then invoke the real method (like in recording step) and wrap the collected information into RecordedInformation and persist it as you like!
} catch (InvocationTargetException e) {
throw e.getTargetException();
} catch (Exception e) {
throw new RuntimeException("unexpected invocation exception: " +
e.getMessage());
} finally {
// do nothing
}
return result;
}
}
}
如果你想记录方法调用,你只需要得到一个 API 代理,如下所示:
MyApi realApi = new RealApi(); // using new or whatever way get your service implementation (API implementation)
MyApi myApiWithRecorder = (MyApi) RecordReplyManager.newInstance(realApi, true); // true for recording
myApiWithRecorder.getMySpouse("richard"); // to record getMySpouse
myApiWithRecorder.getMyAge("parker"); // to record getMyAge
...
并重播您需要的所有内容:
MyApi realApi = new RealApi(); // using new or whatever way get your service implementation (API implementation)
MyApi myApiWithReplayer = (MyApi) RecordReplyManager.newInstance(realApi, false); // false for replaying
myApiWithReplayer.getMySpouse("richard"); // to replay getMySpouse
myApiWithRecorder.getMyAge("parker"); // to replay getMyAge
...
你完成了!
编辑:
记录器和回放器的基本步骤可以按照上述方式完成。现在由您决定如何使用或执行这些步骤。您可以在记录器和回放器代码块中做任何您想做的事情和您喜欢的任何事情,然后选择您的实现!