import {IAspect, IPointcut, IComponent, IAdvice} from "../../type/interface" import {getInstanceMethods} from "../../util" import {PojoType} from "../../type/type" import DecorateRegistCenter from "../DecorateRegistCenter" import { AdviceType } from "../../enum" import JoinPoint from "../../type/impl/aop/advice/JoinPoint" export default class AspectInterceptor{ private static inited: boolean = false private instance: PojoType private hitMethods: Map> = new Map() constructor(instance: PojoType = {}){ if(!AspectInterceptor.inited){ this.init() AspectInterceptor.inited = true } this.instance = instance this.getHitMethods() } private init(): void{ const { aspects = >[], pointcuts = >[], advices = >[] } = DecorateRegistCenter aspects.forEach((aspect: IAspect): void => { aspect.setPointcuts(pointcuts, advices) }) DecorateRegistCenter.aspects = aspects } public getHitMethods(): void{ const {aspects = >[]} = DecorateRegistCenter const {ownMethods = [], prototypeMethods = []}: PojoType = getInstanceMethods(this.instance) const instanceMethods = [...ownMethods, ...prototypeMethods] let {packageName = ''} = this.instance.meta.component aspects.forEach((aspect: IAspect): void => { const {pointcuts = []} = aspect pointcuts.forEach((pointcut: IPointcut): void => { const {advices, execution} = pointcut; instanceMethods.forEach((method: Function) => { packageName = packageName + '.' + method.name + '()' if(execution.test(packageName)){ const existedMethod = > this.hitMethods.get(method) if(existedMethod){ existedMethod.push(...advices) }else{ this.hitMethods.set(method, advices) } } }) }) }) } public async beforeHandler(target: Function, ctx: any, args: Array): Promise{ const functions: Array = [...this.hitMethods.keys()] functions.forEach(async (fun: Function) => { const advices = > this.hitMethods.get(fun) const beforeAdvices = > advices.filter(advice => advice.type === AdviceType.BEFORE) || [] beforeAdvices.forEach(async ({type, value: handler, cost}: IAdvice) => { const joinPoint = new JoinPoint({args, methodName: handler.name, declareClassName: cost.name}) await (handler.__caller__)[handler.name](joinPoint) }) }) return {target, ctx, args} } public async afterHandler(target: Function, ctx: any, args: Array, process: any): Promise{ const functions: Array = [...this.hitMethods.keys()] functions.forEach(async (fun: Function) => { const advices = > this.hitMethods.get(fun) const afterAdvices = > advices.filter(advice => advice.type === AdviceType.AFTER) || [] afterAdvices.forEach(async ({type, value: handler, cost}: IAdvice) => { const joinPoint = new JoinPoint({args, methodName: handler.name, declareClassName: cost.name}) await (handler.__caller__)[handler.name](joinPoint, process) }) }) return {target, ctx, args} } }