1. 程式人生 > >Spring系列(3/4)----一個較為完善的模型(完)

Spring系列(3/4)----一個較為完善的模型(完)

接上一篇,我們繼續來完善這個模型,我們為附加責任類定義了一個介面,這樣,只要實現這個介面的類都可以註冊,接收代理類的呼叫通知;同時為了更好的互動,我們還定義了一個呼叫引數介面,和一個具體的呼叫引數類,接下來,我們再看看代理類:

/// <summary>
    /// 代理類,從AClass繼承.
    /// </summary>
    public class ProxyAClass1 : AClass
    {
      
        private AClass _target;
        public Dictionary<IMethodExecNotify,MethodSubjectType> _observers = null;
        /// <summary>
        /// 建構函式,需傳入目標類例項.
        /// </summary>
        /// <param name="target"></param>
        public ProxyAClass1(AClass Target)
        {
            _target = Target;
            _observers = new Dictionary<IMethodExecNotify,MethodSubjectType>();
        }
        public void RegisterOberver(IMethodExecNotify Observer,MethodSubjectType)
        {
            //.........
        }
        public void RemoveOberver(IMethodExecNotify Observer)
        {
            //..........
        }
        /// <summary>
        /// 執行方法例項.
        /// </summary>
        public override void Save()
        {
            object theRet = null;
            try
            {
                MethodInfo theMI = _target.GetType().GetMethod("Save",new Type[]{});
                var theAs = from item in _observers
                           where item.Value==MethodSubjectType.A
                           select item.Key;
                foreach(var item in theAs)
                {
                    object[] theParams = new object[]{};
                    IMethodInvocation theInvocation = new NotifyInvocation(_target,theMI,theParams);
                    item.SubjectMethodExecuting(theInvocation);

                }
                bool CanExecuteTargetMethod = true;
                 var theBs = from item in _observers
                           where item.Value==MethodSubjectType.B1
                           select item.Key;
                foreach(var item in theBs)
                {
                    object[] theParams = new object[]{};
                    IMethodInvocation theInvocation = new NotifyInvocation(_target,theMI,theParams);
                   CanExecuteTargetMethod = CanExecuteTargetMethod && bool.Parse(item.SubjectMethodExecuting(theInvocation).ToString());

                }
                if(CanExecuteTargetMethod==true)
                {
                    theRet = _target.Save(); 
                    //.......
                }
                //.....
                return theRet;

            }
            catch
            {
                //.......
            }
            finally
            {
                //......
            }
        }
    }

上面的呼叫比較複雜,實際應用可能不需要分這麼多切入點。對於可以阻止目標類方法執行的邏輯(紅色程式碼部分),可以根據自己的需要來決定如何決策。

但目前這個代理類作為一個靜態示例還是可以的,但要作為動態代理類,跟前面的最初的代理原型一樣,無法使用,因為註冊管理功能無法使用,編譯上過不去,如果採用反射來呼叫,是可以,但每次都這樣使用,很麻煩。當然,這個改善很容易,只要將觀察者類集合作為引數在建構函式中傳遞進去就可以了。但註冊管理的責任誰來負責呢?我們前面分析過,因為代理類需要動態生成,而且動態代理類的形式和邏輯基本都一致,也適合動態生成,為了使用方便,我們可以提供一個工廠類來專門負責這件事情。那麼自然而然,觀察者註冊管理的功能也自然由其完成,代理類工廠在構造代理類的時候,再將觀察者集合作為建構函式的引數傳入代理類,當然,觀察者的通知執行還是由代理類來完成。而代理類工廠就是這個系列中第1篇中提到MyProxyFactory類的作用。

到這裡,面向AOP程式設計的動態代理模型就基本成型了,當然,還有許多地方可以改善,但原理如此,大家可以根據自己的需要去繼續改造。

下一篇,我們就來總結一下動態代理技術。