Redkale 让你重新认识Java

        Java 已经走过了二十二个年头,依靠强大的功能、庞大的开发社区和无人能及的生态系统,成为当之无愧的业界之王。

  太臃肿

        如今在Java界,Tomcat、Struts2、Hibernate、MyBatis、Jetty、Spring MVC/Spring Boot/Spring XXX这些框架大家都耳熟能详,似乎不懂两三个以上都不好意思说自己会Java。在一些新手眼里,Java就是Tomcat、Java就是Spring。2004年发布正式版的Spring以其轻量著称,一战成名,打败了J2EE,成为Java事实上的"标准"。然而经过十几年的发展,其生态越来越庞大,功能的增多,复杂的配置,兼容性,历史包袱,使得整个框架体系越来越臃肿,还有不计其数的衍生插件,已经不比当年J2EE轻多少了。在那个JBuilder还是主流IDE的年代,建一个Web系统还是比较简单,除了Tomcat比较大点,其他都算轻量。现在很多人建一个Web项目,需要复杂的Maven建工程,一行代码还没开始写,仅仅是导入SSH/SSM这些框架就需要好几十M,还得进行一堆SSH配置,简单的日志都需要配备log4j/snf4j。可能只是简单的管理系统,必须要搞这么复杂吗? 如今一个1-2M的框架大家都会觉得算轻量级,MyBatis是JDBC基础上的再次封装,jar包大小近6M,但比Hibernate还是轻量些。这些只是基础框架,如果系统还需要其他功能性的框架(Lucene、Mail、Json) 会使开发包更大。同时大量的开源框架抑制了新JDK的普及,NIO出来都十五年, AIO(NIO.2)也出来六年了,如今还有很多人把NIO给贴上高性能的标签,JDK 5--Java第一个重大更新的版本在2004年发布,直到五-六年后Spring的注解方式才得到普及, Java第二个重大更新的版本JDK 8发布也有三年了,大部分人还停留在只识语法糖Lambda的层级,在JDK功能越来越强大的情况下,开发Java系统并不简化多少。相对于现在流行的NodeJs做个Web系统来说,Java就是个巨无霸。其实呢,Java无需这么复杂,真的可以很简单。

  异步呢

        用Java开发异步系统是件很难的事情,首先Java规范中异步接口很少,Servlet 3.0虽然支持异步,也出来好几年了,但现在直接用Servlet写代码的人已经不多,而基于Servlet的Struts、Spring Boot这些框架又没把异步太当回事,基本都是实现的Servet同步方法。JDBC更是迄今为止还没有异步接口。其次开源框架以异步接口为主的凤毛麟角。 所以Java程序员在写业务代码时基本都是用同步方式,特别是最耗时的数据源操作JDBC无法异步。

http.post("/url", {id:10}, function(request, response) {
  service.getResource(request, function(result){
    response.write(JSON.stringify(result));
    response.end();
  });
});

var mysql = require('mysql');
var pool  = mysql.createPool(config);
pool.getConnection(function(err, connection) {
  connection.query( 'SELECT * FROM table', function(err, rows) {
    connection.end();
  });
});

        而在NodeJs里,IO操作都是异步的。这也是为什么有的用Nodejs做的系统比Java还快。Java在语言上和(NIO/NIO.2)框架的性能优势弥补不了同步的副作用。

  新设计

        Redkale 一个全新设计的Java异步微服务框架。集HTTP、WebSocket、REST、JSON、RPC、DB操作、依赖注入等功能于一身,其jar包大小仅790K,且不依赖任何第三方包。

        从以上代码可以看出,根据优先级选择Constructor,为了减少学习成本,Creator直接重用了java.beans.ConstructorProperties注解,又因ConstructorProperties只能标记在Constructor上,因此定义一个Creator.ConstructorParameters注解,用于标记在Creator的create方法上。

public class Record {

    private final int id;

    private String name;

    @ConstructorProperties({"id", "name"})
    Record(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


Record.class通过ASM自动构建与Record同package的Creator类如下:

public final class Record_DynCreator implements Creator<Record> {

    @Override
    @Creator.ConstructorParameters({"id", "name"})
    public Record create(Object... params) {
        if (params[0] == null) params[0] = 0;
        return new Record((Integer) params[0], (String) params[1]);
    }
}

        如上代码,若构造参数是primitive类,而Creator.create传入的参数可能是null,因此需要给null的primitive对象赋予默认值0。细心的人可能发现了Record的构造函数并不是public的,虽然Record_DynCreator与Record在同一package,但由于两者不是同一个ClassLoader,故不能直接new Record。Redkale曲线救国,通过URLClassLoader的私有方法在Record.class的ClassLoader加载Record_DynCreator。

if (loader instanceof URLClassLoader && !Modifier.isPublic(constructor.getModifiers())) {
    try {
        final URLClassLoader urlLoader = (URLClassLoader) loader;
        final URL url = new URL("memclass", "localhost", -1, "/" + newDynName.replace('/', '.') + "/", new URLStreamHandler() {
            @Override
            protected URLConnection openConnection(URL u) throws IOException {
                return new URLConnection(u) {
                    @Override
                    public void connect() throws IOException {
                    }

                    @Override
                    public InputStream getInputStream() throws IOException {
                        return new ByteArrayInputStream(bytes);
                    }
                };
            }
        });
        Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        addURLMethod.setAccessible(true);
        addURLMethod.invoke(urlLoader, url);
        resultClazz = urlLoader.loadClass(newDynName.replace('/', '.'));
    } catch (Throwable t) { //异常无需理会, 使用下一种loader方式
        t.printStackTrace();
    }
}

        如上代码,构建一个虚拟协议的URL来实现加载,若Record.class的ClassLoader不是URLClassLoader导致resultClazz为null则会抛出异常。

        Creator是一个典型通过ASM构建一个简单功能地动态类,同类型还有 org.redkale.util.Attributeorg.redkale.util.Reproduce


        转载请注明出处:https://redkale.org/article_regain.html