use of rpc.turbo.config.MethodConfig in project turbo-rpc by hank-whu.
the class RemoteServiceFactory method generateRemoteObject.
private Object generateRemoteObject(App app, Class<?> clazz, Collection<MethodConfig> configs) throws Exception {
if (app == null) {
throw new RuntimeException("app must not be null");
}
if (clazz == null) {
throw new RuntimeException("clazz must not be null");
}
if (configs == null || configs.isEmpty()) {
throw new RuntimeException("configs must not be empty");
}
for (MethodConfig config : configs) {
if (config == null) {
throw new RuntimeException("config must not be null");
}
if (config.method == null) {
throw new RuntimeException("config.method must not be null");
}
if (config.timeout < 1) {
throw new RuntimeException("config.timeout must > 0");
}
if (config.timeout > 5 * 60 * 1000) {
throw new RuntimeException("config.timeout must < 5 * 60 * 1000 (5 mintues)");
}
}
Method[] allMethods = clazz.getMethods();
List<Method> allPublicMethods = //
Stream.of(//
allMethods).filter(//
m -> Modifier.isPublic(m.getModifiers())).filter(//
m -> !Modifier.isStatic(m.getModifiers())).peek(m -> {
if (!CompletableFuture.class.equals(m.getReturnType())) {
throw new RuntimeException("method return-type must be CompletableFuture, " + InvokerUtils.getServiceMethodName("", "", m));
}
}).collect(Collectors.toList());
if (configs.size() != allPublicMethods.size()) {
throw new RuntimeException("configs must contains all the interface's methods");
}
for (Method method : allMethods) {
if (!CompletableFuture.class.equals(method.getReturnType())) {
throw new RuntimeException("method return-type must be CompletableFuture, " + method);
}
if (!configs.stream().anyMatch(config -> config.method.equals(method))) {
throw new RuntimeException("configs must contains the method: " + method);
}
}
final String remoteClassName = //
clazz.getName() + "_RemoteService_" + UUID.randomUUID().toString().replace("-", "");
// 创建类
ClassPool pool = ClassPool.getDefault();
CtClass remoteCtClass = pool.makeClass(remoteClassName);
CtClass[] interfaces = { pool.getCtClass(clazz.getName()), pool.getCtClass(RemoteInterface.class.getName()) };
remoteCtClass.setInterfaces(interfaces);
// 添加私有成员app
CtField appField = new CtField(pool.get(App.class.getName()), "app", remoteCtClass);
appField.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
remoteCtClass.addField(appField);
// 添加get方法
remoteCtClass.addMethod(CtNewMethod.getter("getApp", appField));
// 添加有参的构造函数
CtConstructor constructor1 = new CtConstructor(new CtClass[] { pool.get(App.class.getName()) }, remoteCtClass);
constructor1.setBody("{$0.app = $1;}");
remoteCtClass.addConstructor(constructor1);
for (MethodConfig config : configs) {
Method method = config.method;
Class<? extends MethodParam> methodParamClass = MethodParamClassFactory.createClass(method);
long timeout = config.timeout;
// 添加私有成员failoverInvoker
String failoverFieldName = getFailoverInvokerFieldName(app, method);
CtField failoverField = new CtField(pool.get(Invoker.class.getName()), failoverFieldName, remoteCtClass);
appField.setModifiers(Modifier.PRIVATE);
remoteCtClass.addField(failoverField);
StringBuilder methodBuilder = new StringBuilder();
methodBuilder.append("public ");
methodBuilder.append(method.getReturnType().getName());
methodBuilder.append(" ");
methodBuilder.append(method.getName());
methodBuilder.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> parameterType = parameterTypes[i];
methodBuilder.append(parameterType.getName());
methodBuilder.append(" param");
methodBuilder.append(i);
if (i != parameterTypes.length - 1) {
methodBuilder.append(", ");
}
}
methodBuilder.append("){\r\n");
methodBuilder.append(" return ");
if (config.ignore) {
if (logger.isInfoEnabled()) {
logger.info(InvokerUtils.getServiceMethodName(app.group, app.app, config.method) + " ignore");
}
methodBuilder.append("$remote_ignore()");
} else {
if (logger.isInfoEnabled()) {
logger.info(//
InvokerUtils.getServiceMethodName(app.group, app.app, config.method) + " register, config:" + config);
}
methodBuilder.append("$remote_execute(");
methodBuilder.append(app.getMethodId(method));
methodBuilder.append(", ");
methodBuilder.append(timeout);
methodBuilder.append("L, ");
methodBuilder.append("new ");
methodBuilder.append(methodParamClass.getName());
methodBuilder.append("(");
for (int i = 0; i < parameterTypes.length; i++) {
methodBuilder.append("param");
methodBuilder.append(i);
if (i != parameterTypes.length - 1) {
methodBuilder.append(",");
}
}
methodBuilder.append("), ");
methodBuilder.append(failoverFieldName);
methodBuilder.append(")");
}
methodBuilder.append(";\r\n}");
CtMethod m = CtNewMethod.make(methodBuilder.toString(), remoteCtClass);
remoteCtClass.addMethod(m);
}
Class<?> invokerClass = remoteCtClass.toClass();
return invokerClass.getConstructor(App.class).newInstance(app);
}
Aggregations