利用AOP写2PC框架(一)
并不是很想写这个系列,因为这个2pc单独写一个小架构有点鸡肋。不过也不知道写什么了,先写了再说吧。
整个流程如下图:
关于AOP系列的文章很多,我这里也再重复造一下轮子。
首先,我们定义了一个IAopProxy,用于给AopProxyFactory用来创建Proxy实例的接口,代码如下:
public interface IAopProxy { AopProxyBase CreateAopProxyInstance(MarshalByRefObject obj, Type type); }
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); }
同时,我们定义了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(); } }
可以看到在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); } } }
那道这里Aop的基础类就搭建完毕了,具体的拦截后,要做什么,则需要去继承于我们的抽象类AopProxyBase,然后复写After和Before去做一些拦截,记录的工作。
本人对代码不做任何知识产权限制,也不保证所有的代码皆为原创。