轻量级IOC框架KoaBoot的问世

2,899 阅读5分钟

相关链接

基于此文章的优化KoaBoot框架

KoaBoot框架的使用教程

压阵效果图,见此图都给我点赞,好人一生十八胎

项目启动

image.png

控制器

image.png

请求效果

image.png

这里小吹一波,从未见过如此优雅的Koa开发

Koa开发的痛点

当我想请求一个接口,使用Koa编写如下

import Koa, { Context } from 'koa'
import KoaRouter from 'koa-router'
import KoaJSON from 'koa-json';

const app = new Koa();
const router = new KoaRouter({ prefix: "/admin" });

app.use(KoaJSON());
app.use(router.routes());

router.post("/list", async (ctx:Context ) => {
    ctx.body = {
        code: 200,
        data: null,
        message: "请求成功"
    }
})

router.get("/list/1", async (ctx:Context ) => {
    ctx.body = {
        code: 200,
        data: ctx.request.query,
        message: "请求成功"
    }
})

app.listen(3002);

假设一个功能上有8个接口,那么我每个接口都是使用 router.get 或者 router.post 形式进行开发,到后面一个TS文件上会有多个这样的形式(如上图的GET请求),代码看起来不够优雅美观,负责处理响应的结尾也没有进行统一返回,可以是各种各样的数据结构。对于害怕麻烦的程序员来说这是一件非常糟糕的事情,每次响应我都要重新写一次响应的数据结构。这对于想偷懒的程序员来说是不可容忍的。综上所述,所有的这些问题都会在Koa-Boot中得到解决。

友好的Koa-Boot开发

在前面的示例中体现了Koa开发的痛点,那么Koa-Boot如何解决的呢,请看下面的示例

import { AutoWired, Controller, RequestMapping, GetMapping, PostMapping } from '../../framework/src/main/node/context/Decorator'
import SystemService from '../service/SystemService';
import Result from '../../framework/src/main/node/mvc/Result';
import { Context } from 'koa';
import { ParsedUrlQuery } from 'querystring';

@Controller
@RequestMapping("/admin")
class SystemController {

    @AutoWired
    private systemService: SystemService;
    
    @PostMapping("/list")
    public test(): Result<string> { 
        return Result.success(this.systemService.test());
    }
    
    @GetMapping("/list/1")
    public test1(ctx: Context): Result<ParsedUrlQuery> {
        return Result.success(ctx.request.query);
    }
}

export default SystemController;

在配合装饰器使用的Koa开发,从开发效果上看,一个TS文件就只有一个类,每一个类上的方法对应着一个功能请求。并且在这里使用了MVC的开发模式,让代码看起来结构分明。并且有明确的返回值以及返回值的类型定义。开发一个接口只需要在功能类上添加一个方法,写上一个装饰器就完成了一个接口功能的开发。

Koa-Boot 如何做到装饰器开发呢

对于使用装饰器开发这个想法,我是基于Java的SpringBoot框架的来的灵感,在我了解到TS中的装饰器时,发现装饰器的功能和作用都跟Java的注解类似。都是对于某个方法,或者某个类的功能增强。对此我大胆尝试了一番。封装Koa框架使用装饰器开发。

IOC容器

是的,你没有看错,Koa-Boot 延续使用了IOC这个编程思想,使用IOC的好处在于开发者不需要关心类与类依赖关系和类的实例化创建。对于开发者来说你只管定义一个类,剩下的交给IOC容器处理。那么Koa-Boot是如何实现IOC的,请看下面的示例

image.png

在示例中可以看到 DefaultListableBeanFactory 类,这个类是核心类,所有经过Koa-Boot扫描并且创建的类的实例都会放入 singleton 属性当中,该属性作为存储对象的容器,也就是IOC容器

依赖注入

有了IOC容器,自然就必不可少的依赖注入,在Spring中有一个经典的问题,那就是循环依赖注入问题,在Spring底层里都是用反射进行依赖注入,在Spring中创建一个对象时,都会把对象上的属性通过反射注入,如果两个类都相互注入Spring就会造成循环依赖的问题。那么在Koa-Boot中如何避免的呢。请看下面示例

image.png

看的一脸懵逼是吧,那必须的,别人的代码怎么可能看得懂。示例中这段代码是Koa-Boot依赖注入和对象放入IOC容器的关键代码,因为TS中的装饰器特性,类的实例早就提前创建好了,并且放在了一个缓冲类中也就是 BeanDefinition。TS的装饰器只有在实例化后才会调用,这里跟Java里的注解不同,在Java中注解是标记一个类,然后根据Java提供的Api获取到注解所标记的类或者方法等等。在TS里的装饰只能实例化类后才会调用,因此在类的扫描阶段直接就创建好对象并且放入BeanDefinitionzh这个类中缓存起来了,属性注入依赖于装饰器 @AutoWired 装饰的属性,会给装饰的属性打上一个标记,然后Koa-Boot会根据这些标记进行属性注入直接解决Spring中的循环依赖问题,因为对象早就已经创建好了。

Koa的封装

完成了IOC容器后,对于Koa的封装就简单很多,Koa-Boot提供一个KoaBootRouter类,装饰器 @RequestMapping、@PostMapping 、@GetMapping 执行的时候,会构造 KoaBootRouter 类的对象,Koa-Boot会通过 KoaBootRouter 对象动态的创建Koa的路由从而完成接口的开发,那么Koa-Boot中是如何解析的呢,请看下面的示例

image.png 此方法是负责解析KoaBootRouter对象,并且构造KoaRouter对象的方法,构造出来的对象会在解析完成后在Koa中统一起注册

结语

以上就是对于Koa装饰器开发的一些基础介绍,本次Demo是一个突发奇想的产物,也只是做了一些简单的封装,无法应对企业级开发,但是对于个人开发来说完全没问题,Koa-Boot不管是开发体验,还是想学习后端的前端同学来说都是不错的项目。可以无缝进入开发状态,语言都不需要更换,直接就可以进行代码编写。有用给个鼓励支持下,谢谢少侠!!

项目代码传送门