zoukankan      html  css  js  c++  java
  • 利用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去做一些拦截,记录的工作。

    本人对代码不做任何知识产权限制,也不保证所有的代码皆为原创。
  • 相关阅读:
    模板模式创建一个poi导出功能
    vim python和golang开发环境配置
    vim快捷键
    golang聊天室
    goroutine与channels
    Redis中的GETBIT和SETBIT(转载)
    二叉树
    满二叉树与完全二叉树
    拓扑排序
    ZigZag Conversion
  • 原文地址:https://www.cnblogs.com/selfteam/p/3975010.html
Copyright © 2011-2022 走看看