Socket
Socket
Sign inDemoInstall

j-spring

Package Overview
Dependencies
4
Maintainers
1
Versions
29
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    j-spring

> Spring for TS


Version published
Weekly downloads
2
decreased by-71.43%
Maintainers
1
Created
Weekly downloads
 

Readme

Source

J-SPRING

Spring for TS

运行步骤:

  • 一.注解解析

  • 1.1 主力主要查看 SpringAnnotation.ts 里面 注解的实现 以及 annotation.test.ts 里面对注解的扩展。

  • 1.2 这里有一个难点,就是理解 SpringContext 中的 SwapBeanDefine 类,这个类是用来描述辅助描述 bean 的元(类,方法,参数,字段)信息的。

  • 1.3 还要系统的复习一遍 TS 的注解实现以及反射。

  • 1.4 注解的运行在容器启动之前,所以在检索注解的时候会搜集指定的 bean(后置处理器),供后面容器的运行。

  • 二.日志

  • 1.1 默认启动内置日志,使用 console 打印。配置第三方后,委托给第三方运行.

  • 1.2 调用 spring.loadLogger(op: (r: ResourceOperate) => Logger) 使用第三方日志功能。第三方日志无法使用容器功能,只能通过 ResourceOperate 读取 spring 的配置。

  • 三.spring 工厂

  • 3.1 首先打印所有检索到的配置项(通过@Value 注解触发搜集到的配置信息)

  • 3.2 实例化后置处理器(通过@Component 扫描的实现 BeanPostProcessor 接口的 bean),根据 sort 属性决定运行顺序。

  • 3.3 随后装配手动注入的类(通过 spring.bind|bindList|bindMoudle)

  • 四.容器操作

  • 4.1 通过 launch 运行容器中启动类(该类必须包含 main 方法),找到后直接调用 main 方法。

  • 4.2 通过 getBean 获取容器中的指定类。

  • 4.3 通过 replaceClass 调换容器中的指定类,需要在工厂实例化之前操作

  • 五.模块启动器 starter

  • 5.1 设计原因,解决模块间的启动顺序和依赖关系。 例如模块(web,mysql)需要先启动 mysql 然后启动 web。

  • 5.2 这里存在一个延迟装配的概念,例如 web 模块中可能导入了 mysql 的模块,但是工厂启动时无法像 web 中装配 mysql 的模块,因为 Mysql 的模块需要在 stater 执行后注入到 spring 容器中。所以工厂将这些装配信息(例如 web 缺少 mysql.db 模块)记录到 lazyAutowiredList 中。每当一个启动器执行时,就将未装配的 lazyAutowiredList 信息尝试装配一次!当所有 starter 启动后,仍然存在未装配的记录,则抛出异常‘依赖不满足’。

  • 5.3 spring 调用 invokeStarter 执行异步启动器,启动顺序由手动注入顺序决定。

spring
  .loadConfig(config) //加载配置
  .loadLogger() //设置日志
  .bindModule([springWebModule, springWebConfig, controllerClassList]) //绑定模块
  .invokeStarter();

install

npm install j-spring

Usage

example

  import { spring,Component,Autowired } from "j-spring";

  it('autowired by special interface',()=>{

    interface A {
      v():number;
    }

    @Component()
    class A1 implements A{
      v(): number {
        return 1;
      }
    }

    @Component()
    class A2 implements A{
      v(): number {
        return 2;
      }
    }

    @Component()
    class Application {

      @Autowired<A>({clazz:A1})
      a1:A;

      @Autowired<A>({clazz:A2})
      a2:A;

      main(c:number){
        return this.a1.v()+this.a2.v()+c;
      }
    }

    expect(spring.getBean(Application).main(3)).toBe(6);

  })

inject profile infomation

import { spring,Component,Autowired } from "j-spring";

describe('resource config load test',()=>{

  @Component()
  class Student {
      @Value({path:'student.name',type:String})
      name:String;
      @Value({path:'student.age',type:Number})
      age:20;
      @Value({path:'student.city',type:String})
      city:String

      getMsg(){
          return ''+this.name+this.age+this.city;
      }
  }


  @Component()
  class Application {

      @Value({path:'app.msg',type:String})
      appMsg:string;

      @Autowired({clazz:Student})
      student:Student;

      public main(){
          return this.appMsg+this.student.getMsg();
      }

  }

  it('A simple set value',()=>{

      spring.loadConfig({
        'app.msg':'hello',
        student:{
            name:'lina',
            age:20,
            city:'youda'
        }
      })

      expect(spring.launch(Application)).toEqual(`hello! my name is lina and 20 years old!`)

  })

})

aop

it('test sample Aop',()=>{

    import { spring,BeanPostProcessor,Component } from "j-spring";

    //create Annotation
    const SupperCaseParamter = spring.methodAnnotationGenerator('SupperCaseParamter',{})

    @Component()
    class SupperCaseParamterBeanProcessor implements BeanPostProcessor {
        getSort(): number {
            return 100;
        }
        postProcessBeforeInitialization(bean: any, _beanDefine: BeanDefine): Object {
            return bean;
        }
        postProcessAfterInitialization(bean: any, beanDefine: BeanDefine): Object {
            beanDefine.methodList.filter(m => m.hasAnnotation(SupperCaseParamter)).forEach(m => {

                const method = bean[m.name];

                bean[m.name] = function(...args:any[]){
                    return  method.apply(bean,args.map(a => {
                        return typeof a === 'string' ? (a as string).toUpperCase() : a;
                    }));
                }

            })
            return bean;
        }

    }

    @Component()
    class Application {

        @SupperCaseParamter
        main(name:string){
            return name;
        }

    }

    expect(spring.bind(SupperCaseParamterBeanProcessor).getBean(Application).main('hello')).toEqual('HELLO');

})

costom annotation

import { spring, SpringContainer } from '../src';

//diy annotation
const Controller = (path: string) =>
  spring.classAnnotationGenerator('Controller', { path }, Controller);

const ResfulApi = spring.classAnnotationGenerator('ResfulApi', {});

const Inject = (path: string) =>
  spring.fieldAnnotationGenerator('Inject', { path }, Inject);

const Get = (path: string) =>
  spring.methodAnnotationGenerator('Get', { path }, Get);

const Query = (fieldName: string) =>
  spring.paramterAnnotationGenerator('Query', fieldName, {}, Query);

describe('test custom annotation', () => {
  it('it should be work', () => {
    @Controller('/apiController')
    @ResfulApi
    class ApiController extends SpringContainer {
      @Inject('small pigBank')
      pigBank: String;

      @Get('/say')
      async say(@Query('user') user: string) {
        return user;
      }

      main() {
        let result: any[] = [];

        this.getBeanDefineMap().forEach((_v, k) => {
          const data = {
            class: k.clazz,
            'anno-length': k.annotationList.length,
            'anno-class': k.annotationList.map(a => a.clazz),
            'anno-param-list': k.annotationList.map(a => a.params),
            'field-list': k.fieldList.map(f => {
              return {
                name: f.name,
                'anno-list': f.annotationList.map(a => a.clazz),
                'anno-param-list': f.annotationList.map(a => a.params),
              };
            }),
            'method-list': k.methodList.map(m => {
              return {
                name: m.name,
                'anno-list': m.annotationList.map(m => m.clazz),
                'anno-params': m.annotationList.map(m => m.params),
                'field-list': m.paramterDefineList.map(pb => {
                  return {
                    name: pb.name,
                    index: pb.index,
                    'anno-list': pb.annotationList.map(a => a.clazz),
                  };
                }),
              };
            }),
          };
          result.push(data);
        });

        return result;
      }
    }

    expect(spring.launch(ApiController)).toEqual([
      {
        class: ApiController,
        'anno-length': 2,
        'anno-class': [ResfulApi, Controller],
        'anno-param-list': [{}, { path: '/apiController' }],
        'field-list': [
          {
            name: 'pigBank',
            'anno-list': [Inject],
            'anno-param-list': [{ path: 'small pigBank' }],
          },
        ],
        'method-list': [
          {
            name: 'say',
            'anno-list': [Get],
            'anno-params': [{ path: '/say' }],
            'field-list': [
              {
                name: 'user',
                index: 0,
                'anno-list': [Query],
              },
            ],
          },
        ],
      },
    ]);
  });
});

replace dependence

it('replace autowired class', () => {
  @Component()
  class A {
    value() {
      return 1;
    }
  }

  @Component()
  class A100 extends A {
    value(): number {
      return 100;
    }
  }

  @Component()
  class Application {
    @Autowired({ clazz: A })
    a: A;

    main() {
      return this.a.value();
    }
  }

  expect(spring.replaceClass(A, A100).launch(Application)).toBe(100);
});

Keywords

FAQs

Last updated on 15 Nov 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc