Search in sources :

Example 1 with MethodConfig

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);
}
Also used : CtMethod(javassist.CtMethod) CompletableFuture(java.util.concurrent.CompletableFuture) CtClass(javassist.CtClass) CtNewMethod(javassist.CtNewMethod) App(rpc.turbo.transport.client.App) CtConstructor(javassist.CtConstructor) MethodConfig(rpc.turbo.config.MethodConfig) Method(java.lang.reflect.Method) Invoker(rpc.turbo.invoke.Invoker) TurboService(rpc.turbo.annotation.TurboService) Collection(java.util.Collection) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) MethodParam(rpc.turbo.param.MethodParam) IOException(java.io.IOException) UUID(java.util.UUID) Field(java.lang.reflect.Field) Collectors(java.util.stream.Collectors) CtField(javassist.CtField) MethodParamClassFactory(rpc.turbo.param.MethodParamClassFactory) List(java.util.List) InvokerUtils(rpc.turbo.invoke.InvokerUtils) Stream(java.util.stream.Stream) Closeable(java.io.Closeable) Modifier(java.lang.reflect.Modifier) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) ClassPool(javassist.ClassPool) FailoverInvokerFactory(rpc.turbo.invoke.FailoverInvokerFactory) App(rpc.turbo.transport.client.App) ClassPool(javassist.ClassPool) CtMethod(javassist.CtMethod) CtNewMethod(javassist.CtNewMethod) Method(java.lang.reflect.Method) CtConstructor(javassist.CtConstructor) MethodConfig(rpc.turbo.config.MethodConfig) CtClass(javassist.CtClass) CompletableFuture(java.util.concurrent.CompletableFuture) CtField(javassist.CtField) CtClass(javassist.CtClass) CtMethod(javassist.CtMethod)

Aggregations

Closeable (java.io.Closeable)1 IOException (java.io.IOException)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 Modifier (java.lang.reflect.Modifier)1 Collection (java.util.Collection)1 List (java.util.List)1 UUID (java.util.UUID)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1 ClassPool (javassist.ClassPool)1 CtClass (javassist.CtClass)1 CtConstructor (javassist.CtConstructor)1 CtField (javassist.CtField)1 CtMethod (javassist.CtMethod)1 CtNewMethod (javassist.CtNewMethod)1 Log (org.apache.commons.logging.Log)1 LogFactory (org.apache.commons.logging.LogFactory)1