利用AOP写2PC框架(一)

并不是很想写这个系列,因为这个2pc单独写一个小架构有点鸡肋。不过也不知道写什么了,先写了再说吧。

整个流程如下图:

关于AOP系列的文章很多,我这里也再重复造一下轮子。

首先,我们定义了一个IAopProxy,用于给AopProxyFactory用来创建Proxy实例的接口,代码如下:

    public interface IAopProxy
    {
        AopProxyBase CreateAopProxyInstance(MarshalByRefObject obj, Type type);
    }
View Code

AOP截获最重要的就是RealProxy类了,我们写一个AopProxyBase抽象类,继承于RealProxy,代码如下:

public abstract class AopProxyBase : RealProxy
    {
        private readonly MarshalByRefObject target; //默认透明代理
        public AopProxyBase(MarshalByRefObject obj, Type type)
            : base(type)
        {
            this.target = obj;
        }

        public override IMessage Invoke(IMessage msg)
        {
            IMethodCallMessage call = (IMethodCallMessage)msg;

            bool isIntercept = false;

            var attrs = call.MethodBase.GetCustomAttributes(typeof(AopMethodAttribute), false) as AopMethodAttribute[];

            //如果标记了AopMethodAttribute的,才记录。
            if (attrs.Length > 0)
            {
                isIntercept = true;
            }
            
            if (isIntercept)
            {
                this.Before(msg, attrs);
            }

            //如果触发的是构造函数,此时target的构建还未开始
            IConstructionCallMessage ctor = call as IConstructionCallMessage;
            if (ctor != null)
            {
                //获取最底层的默认真实代理
                RealProxy default_proxy = RemotingServices.GetRealProxy(this.target);
                default_proxy.InitializeServerObject(ctor);
                MarshalByRefObject tp = (MarshalByRefObject)this.GetTransparentProxy();

                return EnterpriseServicesHelper.CreateConstructionReturnMessage(ctor, tp);
            }

            IMethodReturnMessage result_msg = RemotingServices.ExecuteMessage(this.target, call);

            if (isIntercept)
            {
                this.After(msg, result_msg, attrs);
            }

            return result_msg;
        }


        public abstract void Before(IMessage requestMsg, AopMethodAttribute[] attrs);

        public abstract void After(IMessage requestMsg, IMessage Respond, AopMethodAttribute[] attrs);

    }
View Code

同时,我们定义了AopAttribute : ProxyAttribute,代码如下:

[AttributeUsage(AttributeTargets.Class)]
    public class AopAttribute : ProxyAttribute
    {
        IAopProxy proxy;
        public AopAttribute(Type factoryType)
        {
            this.proxy = (IAopProxy)AopProxyFactory.CreateInstance(factoryType);
        }

        public override MarshalByRefObject CreateInstance(Type serverType)
        {
            MarshalByRefObject target = base.CreateInstance(serverType);
            
            AopProxyBase rp = this.proxy.CreateAopProxyInstance(target, serverType);

            return (MarshalByRefObject)rp.GetTransparentProxy();
        }
    }
View Code

可以看到在AopAttribute的构造函数里面,有通过Factory去创建被拦截的Class的实例,避免每次都去创建,我加了一个Dictionary作为Cache,代码如下:

 public class AopProxyFactory
    {
        private static AopProxyCache _proxyCollection;

        private static readonly object _syncObject = new object();
        static AopProxyFactory()
        {
            lock (_syncObject)
            {
                if (_proxyCollection == null)
                {
                    _proxyCollection = new AopProxyCache();
                }
            }
        }

        public static IAopProxy CreateInstance(Type type)
        {
            return _proxyCollection[type];
        }
    }



public class AopProxyCache
    {
        public Dictionary<Type, IAopProxy> _proxys;
        private static readonly object _syncObject = new object();

        public AopProxyCache()
        {
            lock (this)
            {
                if (_proxys == null)
                {
                    _proxys = new Dictionary<Type, IAopProxy>();
                }
            }
        }

        public void Add(Type type, IAopProxy proxy)
        {
            if (_proxys == null) throw new ArgumentNullException("proxys is not init");
            lock (_syncObject)
            {
                this._proxys[type] = proxy;
            }
        }

        public IAopProxy Get(Type type)
        {
            IAopProxy proxy;
            if (this._proxys.ContainsKey(type))
            {
                proxy = this._proxys[type];
            }
            else
            {
                lock(_syncObject)
                {
                    if (!this._proxys.ContainsKey(type))
                    {
                        proxy = (IAopProxy)Activator.CreateInstance(type);
                        this.Add(type, proxy);
                    }
                    else
                    {
                        proxy = this._proxys[type];
                    }
                }
            }
            return proxy;
        }

        public IAopProxy this[Type type]
        {
            get
            {
                return this.Get(type);
            }
            set
            {
                this.Add(type, value);
            }
        }
    }
View Code

那道这里Aop的基础类就搭建完毕了,具体的拦截后,要做什么,则需要去继承于我们的抽象类AopProxyBase,然后复写After和Before去做一些拦截,记录的工作。

 

posted on 2014-09-16 15:27  双调  阅读(1428)  评论(0编辑  收藏  举报

导航