**** Passed into module advisor methods to allow the method to, err, advise services!** ** @see The `Advise` facet for more details.** ** @since 1.3.0class MethodAdvisor {internal |MethodInvocation invocation -> Obj?|[] aspects := [,]** The method to adviseconst Method methodinternalnew make(Method method){this.method = method}** Add an aspect that will be called when the method is invoked Void addAdvice(|MethodInvocation invocation -> Obj?| aspect){ aspects.add(aspect)}// given I've never needed to override method advice (and realistically I'm the only one using // afIoc!) we'll not order the advice for now// abstract Void addOrderedAdvice(Str id, Str[] orderingConstraints, |Obj target, Obj[] args| aspect)// abstract Void overrideOrderedAdvice(Str idToOverride, Str id, Str[] orderingConstraints, |Obj target, Obj[] args| aspect)}** As used by aspects to call the method they wrap.** ** The wrapped method is purposely hidden so no-one is tempted to call it directly, use [invoke()]`#invoke` instead. ** The real method is hidden behind this class so multiple Method Advisors can be chained** ** @see The `Advise` facet for more details.** ** @since 1.3.0class MethodInvocation {** The instance of the service the method will be called on Obj service** A mutable list of arguments the method will be called with Obj?[] argsinternal Method? methodinternal Int indexinternal |MethodInvocation invocation -> Obj?|[] aspectsinternalnew make(|This|f){ f(this)}** Call the next method advice in the pipeline, or the real method - you'll never know which! Obj? invoke(){ index++if(index <= aspects.size)return aspects[-index].call(this)return method.callOn(service, args)}}