feat: support Autowired and JSClass inject

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
MiaoWoo 2020-06-17 18:34:01 +08:00
parent 32db0bba56
commit 8a07e85fda
4 changed files with 135 additions and 61 deletions

View File

@ -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"
}
}

View File

@ -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')
}

View File

@ -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<any>) {
return function(proto: any, key: string): void {
return function (serviceIdentifier: interfaces.ServiceIdentifier<any>) {
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<any>, named: string) {
return function(proto: any, key: string): void {
return function (serviceIdentifier: interfaces.ServiceIdentifier<any>, 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<any>, key: string, value: any) {
return function(proto: any, propertyName: string): void {
return function (serviceIdentifier: interfaces.ServiceIdentifier<any>, 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<any>) {
return function(proto: any, key: string): void {
return function (serviceIdentifier: interfaces.ServiceIdentifier<any>) {
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
};
}

View File

@ -1,25 +1,91 @@
import "reflect-metadata";
import { initContainer } from './decorators'
import { interfaces, Container } from 'inversify';
import { fluentProvide } from 'inversify-binding-decorators';
/// <reference types="@ccms/nashorn" />
const provideNamed = (identifier: interfaces.ServiceIdentifier<any>, 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<any>) => {
return fluentProvide(identifier).inSingletonScope().done();
};
/**
*
* @param identifier
* @param name
*/
export const provideNamed = (identifier: interfaces.ServiceIdentifier<any>, name: string) => {
return fluentProvide(identifier).whenTargetNamed(name).done()
}
const DefaultContainer = new Container();
initContainer(DefaultContainer);
/**
*
* @param identifier
*/
export const provideSingleton = (identifier: interfaces.ServiceIdentifier<any>) => {
return fluentProvide(identifier).inSingletonScope().done()
}
/**
*
* @param identifier
*/
export const provideSingletonNamed = (identifier: interfaces.ServiceIdentifier<any>, 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
};