1.2.5-beta • Published 2 years ago

ioc4ts v1.2.5-beta

Weekly downloads
-
License
Apache-2.0
Repository
-
Last release
2 years ago

ioc4ts ( IoC container for TypeScript )

简单介绍

IoC (Inversion of Control,控制反转),最早是从 Spring 框架中接触到这个概念,简单的说就是将创建对象的权力交给 IoC 容器管理,以达到模块之间的松耦合。ioc4ts 框架实现了简单的 IoC 容器,并接入 axios, 完成接口返回数据与对象实例之间的映射。

目前不建议在生产环境中使用 ioc4ts

安装

npm install ioc4ts
# 或者
yarn add ioc4ts

引入

import BeanFactory, { Get, Property, ReturnType, PathVariable } from 'ioc4ts'

配置 tsconfig.json

将 tsconfig.json 中的 experimentalDecorators 选项设置为 true

{
  "experimentalDecorators": true
}

教程

实现的功能如下:

  • ApplicationContext 应用上下文
  • @HttpRequest 注解
  • @Property 注解
  • @ReturnType 注解
  • @Get 注解
  • @Post 注解
  • @Put 注解
  • @Delete 注解
  • @PathVariable 注解
  • @RequestHeader 注解
  • @RequestParam 注解
  • @RequestBody 注解

ApplicationContext 应用上下文

ApplicationContext 是一个单例,通过 getInstance 方法获取 ApplicationContext 的实例。

const context = ApplicationContext.getInstance()

获取 BeanFactory 的方法为 getBeanFactory()

const context = ApplicationContext.getInstance()
const beanFactory = context.getBeanFactory()

@HttpRequest 注解

@HttpRequest 用于修饰一个类,作用是向 BeanFactory 注入这个类的实例作为一个 HttpRequest 的单例,@HttpRequest 修饰的类需要实现 HttpRequestInterface 接口,(注意:如果不实现 HttpRequestInterface 接口的话,也需要提供一个 request 方法,用于实现 Http 请求,这是由于 TypeScript 无法判断类实例是否实现了某个接口)

@HttpRequest()
class AxiosHttpRequest implements HttpRequestInterface {
    private instance: AxiosInstance

    constructor() {
        this.instance = axios.create({ baseURL: 'http://localhost:3000' })
    }

    request(config: HttpRequestConfig<unknown>): Promise<AxiosResponse<Object>> {
        return this.instance.request({
            method: config.method,
            url: config.path,
            params: config.params,
            headers: config.headers,
            data: config.data
        })
    }
}

@Property 注解

@Property 注解用于修饰类的属性,需要提供一个 name 参数,用于定义从源(source: 也就是一个 JSON 对象)中的名为 name 字段中的获取值。注意:@Property 注解目前不会做类型检查

class User {
  @Property('name')
  name: number
}

@ReturnType 注解

@ReturnType 注解用于修饰类的方法,用来定义方法的返回类型,目前需要配合 @Get@Post 等 Http 请求注解一起使用。(注意:类中不要定义同名的静态方法和成员方法!)

class User {
  @ReturnType("User")
  @Get('/user/1')
  getById() {}
}

@Get 注解

@Get 注解用于修饰类的方法,被修饰的方法被调用时,方法体中的代码将不会被执行,取而代之的是执行一个 Http 的 Get 请求。

class User {
  @Get('/user/1')
  static getById() {}
}

@Post 注解

用法同 @Get

class User {
  @Post('/user')
  static create() {}
}

@Put 注解

用法同 @Get

class User {
  @Put('/user/1')
  static modify() {}
}

@Delete 注解

用法同 @Get

class User {
  @Delete('/user/1')
  static delete() {}
}

@PathVariable 注解

@PathVariable 用来修饰方法的参数,用于定义路径变量,需要提供一个 name 参数,与路径字符串中被 {} 包裹的变量名相同。

class User {
  @Get('/user/{id}')
  static getById(@PathVariable("id") id: number) {}
}

@RequestHeader 注解

@RequestHeader 用来修饰方法的参数,用来定义 Http 请求头的某个属性。

class User {
  @Get('/user/1')
  static getById(@RequestHeader("X-Token") token: string) {}
}

@RequestParam 注解

@RequestParam 用来修饰方法的参数,用来定义 Http 请求的某个路径参数。

class User {
  @Get('/user')
  static getByAge(@RequestParam("age") age: number) {}
}

@RequestBody 注解

@RequestBody 用来修饰方法的参数,用来定义 Http 请求的请求体内容。

class User {
  @Post('/user')
  static create(@RequestBody() user: User) {}
}

使用案例

1. 初始化 TypeScript 项目

以 yarn 为例子:

# 初始化项目
yarn init
# 全局安装 TypeScript
yarn global add typescript
# 初始化 TypeScript 项目
tsc -init
# 安装 ioc4ts
yarn add ioc4ts

2. 配置 tsconfig.json

将 tsconfig.json 中的 experimentalDecorators 选项设置为 true, 并配置 include 选项。

{
  "include": ["index.ts"],
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

3. 编写源文件 index.ts

import BeanFactory, { Get, Property, ReturnType, PathVariable } from 'ioc4ts'

class User {
  // Property 没有做类型检查,如果 name 是其他类型也会映射成功
  @Property("name")
  name?: string;

  @Property("age")
  age?: number;

  @Get("/{role}/{ID}")
  @ReturnType("User")
  static find(@PathVariable('role') role: string, @PathVariable('ID') id: number) {
    // 加上 Get 注解以后,方法体内的代码不执行
    console.log("User.find()");
  }

  self() {
    console.log(`我是${this.name}, 我的年龄是${this.age}`);
  }
}

class Teacher {
  @Property("name")
  teacherName?: string;

  @Property("age")
  teacherAge?: string;

  self() {
    console.log(`我是${this.teacherName}, 是一位老师, 我的年龄是${this.teacherAge}`);
  }
}

const beanFactory = BeanFactory.getInstance();
const UserClass = beanFactory.getBeanClass("User");

UserClass.find('user', 1)
  .then((user: User) => {
    user.self();
  })
  .catch((err: any) => {
    console.log(err);
  });

4. 编写后端接口文件 server.js

const http = require('http')

http.createServer((req, res) => {
    if(req.url === '/user/1') {
        console.log(req.url, 'success')
        const user = {
            name: 'zhangsan',
            age: '18'
        }
  
        res.writeHead(200, {'content-type': 'text/json'})
        res.write(JSON.stringify(user))
    } else {
        res.writeHead(404)
    }
    res.end()
}).listen(3000)

console.log("Server is running, listening port 3000 ...")

5. 运行

运行服务器

node server.js

编译 index.ts

tsc

运行编译出来的 index.js

node index.js

6. 更改 index.ts, 再次编译运行,查看效果

ReturnType 注解的值改成 'Teacher' 后,将调用 Teacherself() 方法

@ReturnType("Teacher")
@Get("/user/1")
static list() {}

需要注意的点

  1. 多个文件中的不同类的类名也不能相同,(例如:Teacher 的类名不能设置与 User 相同)
  2. @Property 注解中的值,对应接口返回的字段。
  3. @Property 没有做类型检查,如果 name 是其他类型也会映射成功。
  4. 加上 @Get 注解以后,方法体内的代码console.log("User.find()")将不会被执行。

版本发布计划

1.2.x-beta 版需要实现的功能:

  • JSX 语法解析
  • 嵌套属性实现
  • 实现 @Autowired 注解
  • 假如 UserMapperUserListView 之后定义,UserMapper 找不到的问题需要解决。

示例:

@View("id", "UserListView")
class UserListView {
  @Autowired("UserMapper")
  userMapper: UserMapper
}

class UserMapper {

}

Todos

  • PropertyDefinition 需要实现,并且实现单例 bean 的依赖注入,单例 bean 的循环依赖问题需要解决。
  • 属性注入的类型转换需要实现。
  • 实现 JSX 语法的解析
  • 获取某个 JSX 模块的属性依赖
  • 其他要做的暂时没想到了...
1.2.5-beta

2 years ago

1.2.2-beta

2 years ago

1.1.5-beta

2 years ago

1.1.2-beta

2 years ago

1.2.1-beta

2 years ago

1.2.4-beta

2 years ago

1.1.8-beta

2 years ago

1.1.7-beta

2 years ago

1.1.4-beta

2 years ago

1.1.3-beta

2 years ago

1.2.0-beta

2 years ago

1.1.9-beta

2 years ago

1.1.6-beta

2 years ago

1.2.3-beta

2 years ago

1.1.1-beta

3 years ago

1.1.0-beta

3 years ago

1.0.10-beta

3 years ago

1.0.9-beta

3 years ago

1.0.6-beta

3 years ago

1.0.5-beta

3 years ago

1.0.4-beta

3 years ago

1.0.3-beta

3 years ago

1.0.2-beta

3 years ago

1.0.1-beta

3 years ago

1.0.0

3 years ago