diff --git a/packages/container/package.json b/packages/container/package.json index e4420bd5..3b872d1d 100644 --- a/packages/container/package.json +++ b/packages/container/package.json @@ -25,6 +25,7 @@ }, "dependencies": { "inversify": "^5.0.1", - "inversify-binding-decorators": "^4.0.0" + "inversify-binding-decorators": "^4.0.0", + "@ccms/nashorn": "^0.7.0" } } diff --git a/packages/container/src/constants.ts b/packages/container/src/constants.ts new file mode 100644 index 00000000..28120fbc --- /dev/null +++ b/packages/container/src/constants.ts @@ -0,0 +1,7 @@ +export namespace ioc { + export const Autowired = Symbol('Autowired') + export const Resource = Symbol('Resource') + export const JavaClass = Symbol('JavaClass') + export const JavaInstance = Symbol('JavaInstance') + export const JavaStaticClass = Symbol('JavaStaticClass') +} diff --git a/packages/container/src/decorators.ts b/packages/container/src/decorators.ts index 33bca190..17789407 100644 --- a/packages/container/src/decorators.ts +++ b/packages/container/src/decorators.ts @@ -1,9 +1,9 @@ -import { interfaces, Container } from "inversify"; +import { interfaces, Container } from "inversify" -let _container: Container; +let _container: Container -const ContainerInstance = Symbol.for("@ccms/ioc:Container"); -const INJECTION = Symbol.for("INJECTION"); +const ContainerInstance = Symbol.for("@ccms/ioc:Container") +const INJECTION = Symbol.for("INJECTION") function _proxyGetter( proto: any, @@ -13,17 +13,17 @@ function _proxyGetter( ) { function getter(this: object) { if (doCache && !Reflect.hasMetadata(INJECTION, this, key)) { - Reflect.defineMetadata(INJECTION, resolve(), this, key); + Reflect.defineMetadata(INJECTION, resolve(), this, key) } if (Reflect.hasMetadata(INJECTION, this, key)) { - return Reflect.getMetadata(INJECTION, this, key); + return Reflect.getMetadata(INJECTION, this, key) } else { - return resolve(); + return resolve() } } function setter(this: object, newVal: any) { - Reflect.defineMetadata(INJECTION, newVal, this, key); + Reflect.defineMetadata(INJECTION, newVal, this, key) } Object.defineProperty(proto, key, { @@ -31,63 +31,63 @@ function _proxyGetter( enumerable: true, get: getter, set: setter - }); + }) } function initContainer(container: Container) { - Reflect.defineMetadata(ContainerInstance, container, Reflect); - _container = container; + Reflect.defineMetadata(ContainerInstance, container, Reflect) + return _container = container } function getContainer(): Container { - return _container || Reflect.getMetadata(ContainerInstance, Reflect) + return _container || initContainer(new Container()) } function makePropertyInjectDecorator(doCache: boolean) { - return function(serviceIdentifier: interfaces.ServiceIdentifier) { - return function(proto: any, key: string): void { + return function (serviceIdentifier: interfaces.ServiceIdentifier) { + return function (proto: any, key: string): void { let resolve = () => { - return getContainer().get(serviceIdentifier); - }; - _proxyGetter(proto, key, resolve, doCache); - }; - }; + return getContainer().get(serviceIdentifier) + } + _proxyGetter(proto, key, resolve, doCache) + } + } } function makePropertyInjectNamedDecorator(doCache: boolean) { - return function(serviceIdentifier: interfaces.ServiceIdentifier, named: string) { - return function(proto: any, key: string): void { + return function (serviceIdentifier: interfaces.ServiceIdentifier, named: string) { + return function (proto: any, key: string): void { let resolve = () => { - return getContainer().getNamed(serviceIdentifier, named); - }; - _proxyGetter(proto, key, resolve, doCache); - }; - }; + return getContainer().getNamed(serviceIdentifier, named) + } + _proxyGetter(proto, key, resolve, doCache) + } + } } function makePropertyInjectTaggedDecorator(doCache: boolean) { - return function(serviceIdentifier: interfaces.ServiceIdentifier, key: string, value: any) { - return function(proto: any, propertyName: string): void { + return function (serviceIdentifier: interfaces.ServiceIdentifier, key: string, value: any) { + return function (proto: any, propertyName: string): void { let resolve = () => { - return getContainer().getTagged(serviceIdentifier, key, value); - }; - _proxyGetter(proto, propertyName, resolve, doCache); - }; - }; + return getContainer().getTagged(serviceIdentifier, key, value) + } + _proxyGetter(proto, propertyName, resolve, doCache) + } + } } function makePropertyMultiInjectDecorator(doCache: boolean) { - return function(serviceIdentifier: interfaces.ServiceIdentifier) { - return function(proto: any, key: string): void { + return function (serviceIdentifier: interfaces.ServiceIdentifier) { + return function (proto: any, key: string): void { let resolve = () => { - return getContainer().getAll(serviceIdentifier); - }; - _proxyGetter(proto, key, resolve, doCache); - }; - }; + return getContainer().getAll(serviceIdentifier) + } + _proxyGetter(proto, key, resolve, doCache) + } + } } -let doCache = true; +let doCache = true let lazyInject = makePropertyInjectDecorator(doCache) let lazyInjectNamed = makePropertyInjectNamedDecorator(doCache) @@ -102,4 +102,4 @@ export { lazyInjectNamed, lazyInjectTagged, lazyMultiInject -}; +} diff --git a/packages/container/src/index.ts b/packages/container/src/index.ts index 235eeae2..15bdae90 100644 --- a/packages/container/src/index.ts +++ b/packages/container/src/index.ts @@ -1,25 +1,91 @@ -import "reflect-metadata"; -import { initContainer } from './decorators' -import { interfaces, Container } from 'inversify'; -import { fluentProvide } from 'inversify-binding-decorators'; +/// -const provideNamed = (identifier: interfaces.ServiceIdentifier, name: string) => { - return fluentProvide(identifier).whenTargetNamed(name).done(); -}; +import "reflect-metadata" +import { initContainer, getContainer } from './decorators' +import { interfaces, Container } from 'inversify' +import { fluentProvide } from 'inversify-binding-decorators' +import { ioc } from "./constants" -const provideSingleton = (identifier: interfaces.ServiceIdentifier) => { - return fluentProvide(identifier).inSingletonScope().done(); -}; +/** + * 注册一个命名对象 + * @param identifier 标识符 + * @param name 名称 + */ +export const provideNamed = (identifier: interfaces.ServiceIdentifier, name: string) => { + return fluentProvide(identifier).whenTargetNamed(name).done() +} -const DefaultContainer = new Container(); -initContainer(DefaultContainer); +/** + * 注册一个单例对象 + * @param identifier 标识符 + */ +export const provideSingleton = (identifier: interfaces.ServiceIdentifier) => { + return fluentProvide(identifier).inSingletonScope().done() +} + +/** + * 注册一个单例对象 + * @param identifier 标识符 + */ +export const provideSingletonNamed = (identifier: interfaces.ServiceIdentifier, name: string) => { + return fluentProvide(identifier).inSingletonScope().whenTargetNamed(name).done() +} + +/** + * 获得一个 java.lang.Class + * @param className Java全类名 + */ +export const JavaClass = (className: string) => { + return function (target: any, propertyKey: string, index?: number) { + try { target[propertyKey] = Java.type(className).class; return } catch (error) { } + try { target[propertyKey] = base.getClass(className); return } catch (error) { } + console.warn('JavaClass Inject target', target, 'propertyKey', propertyKey, 'failed!') + } +} + +/** + * 获得一个JS的Java类 + * @param className Java 全类名 + */ +export const JSClass = (className: string) => { + return function (target: any, propertyKey: string, index?: number) { + try { target[propertyKey] = Java.type(className); return } catch (error) { } + try { target[propertyKey] = base.getClass(className).static; return } catch (error) { } + console.warn('JSClass Inject target', target, 'propertyKey', propertyKey, 'failed!') + } +} + +/** + * 自动注入实例由平台实现 + * @param className 类名 + */ +export const Autowired = (className?: string | any) => { + return function (target: any, propertyKey: string) { + target[propertyKey] = getContainer().getNamed(ioc.Autowired, className || propertyKey) + } +} + +/** + * 自动注入资源由平台实现 + * @param className 类名 + */ +export const Resource = (resourceName?: string | any) => { + return function (target: any, propertyKey: string) { + target[propertyKey] = getContainer().getNamed(ioc.Resource, resourceName || propertyKey) + } +} + +export const reduceMetadata = (ctx: interfaces.Context): any => { + return ctx.currentRequest.target.metadata.reduce((result, entry, index) => { + result[entry.key] = entry.value + return result + }, {}) +} + +export const DefaultContainer = new Container() +initContainer(DefaultContainer) export * from 'inversify' +export * from './constants' export * from './decorators' export * from 'inversify-binding-decorators' -export { - fluentProvide, - provideNamed, - provideSingleton, - DefaultContainer -};