并不是很想写这个系列,因为这个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 > )
{
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去做一些拦截,记录的工作。

利用AOP写2PC框架(一)的更多相关文章

  1. 利用AOP写2PC框架(二)

    AOP的底层已经封装好了以后,我们就要开始针对应用层写具体的业务逻辑了. 也就是说我们需要有个类继承于AopProxyBase,并且重写其After,Bofore以达到我们的拦截记录的功能.代码如下: ...

  2. 关于Quartz.NET作业调度框架的一点小小的封装,实现伪AOP写LOG功能

    Quartz.NET是一个非常强大的作业调度框架,适用于各种定时执行的业务处理等,类似于WINDOWS自带的任务计划程序,其中运用Cron表达式来实现各种定时触发条件是我认为最为惊喜的地方. Quar ...

  3. SpringBoot31 整合SpringJDBC、整合MyBatis、利用AOP实现多数据源

    一.整合SpringJDBC 1  JDBC JDBC(Java Data Base Connectivity,Java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系数 ...

  4. 利用AOP切面打印项目中每个接口的运行情况

    1.前言 AOP切面技术,大家应该都听知道,Spring框架的主要功能之一. AOP切面的用途很广,其中一个常见的用途就是打印接口方法的运行日志和运行时间. 日志对于一个项目很是重要,不仅有助于调错, ...

  5. .NET Core的日志[5]:利用TraceSource写日志

    从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试和跟踪信息的日志记录.在.NET ...

  6. 利用AOP与ToStringBuilder简化日志记录

    刚学spring的时候书上就强调spring的核心就是ioc和aop blablabla...... IOC到处都能看到...AOP么刚开始接触的时候使用在声明式事务上面..当时书上还提到一个用到ao ...

  7. Python基础篇【第3篇】: Python异常处理、反射、动态导入、利用反射的web框架

    异常处理 什么是异常? 异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行. 一般情况下,在Python无法正常处理程序时就会发生一个异常.异常是Python对象,表示一个错误.当P ...

  8. 利用多写Redis实现分布式锁原理与实现分析(转)

    利用多写Redis实现分布式锁原理与实现分析   一.关于分布式锁 关于分布式锁,可能绝大部分人都会或多或少涉及到. 我举二个例子:场景一:从前端界面发起一笔支付请求,如果前端没有做防重处理,那么可能 ...

  9. 利用TraceSource写日志

    利用TraceSource写日志 从微软推出第一个版本的.NET Framework的时候,就在“System.Diagnostics”命名空间中提供了Debug和Trace两个类帮助我们完成针对调试 ...

随机推荐

  1. NodeJs之OS

    OS Node.js提供了一些基本的底层操作系统的模块OS. API var os = require('os'); console.log('[arch] 操作系统CPU架构'+os.arch()) ...

  2. Golang, 以17个简短代码片段,切底弄懂 channel 基础

    (原创出处为本博客:http://www.cnblogs.com/linguanh/) 前序: 因为打算自己搞个基于Golang的IM服务器,所以复习了下之前一直没怎么使用的协程.管道等高并发编程知识 ...

  3. Windows server 2012 添加中文语言包(英文转为中文)(离线)

    Windows server 2012 添加中文语言包(英文转为中文)(离线) 相关资料: 公司环境:亚马孙aws虚拟机 英文版Windows2012 中文SQL Server2012安装包,需要安装 ...

  4. ExtJS 4.2 业务开发(二)数据展示和查询

    本篇开始模拟一个船舶管理系统,提供查询.添加.修改船舶的功能,这里介绍其中的数据展示和查询功能. 目录 1. 数据展示 2. 数据查询 3. 在线演示 1. 数据展示 在这里我们将模拟一个船舶管理系统 ...

  5. 再谈C#采集,一个绕过高强度安全验证的采集方案?方案很Low,慎入

    说起采集,其实我是个外行,以前拔过阿里巴巴的客户数据,在我博客的文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 中,介绍过采集用的工具,其实很Low的,分析 ...

  6. Android Studio —— 重装 HAXM

    Android Studio -- 重装 HAXM 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. Android SDK 自带模拟器一直以慢.卡 ...

  7. java中的内部类

    /** * 内部类 ?? * 定义在一个内部的类,被称为内部类. * 内部类里有类体,方法体 * 内部类所在的类,被称为外部类. * --------------------------------- ...

  8. 2016/12/30_Python

    今天主要学习内容: Python: 1.字典的使用 1)怎么创建字典 dicts = {"name":"juncx","age":17} d ...

  9. jenkins无法重启tomcat的原因

    在使用Hudson的执行sh脚本的时候,如果sh脚本是一个后台进程,如 Tomcat 这样的服务.如果使用Hudson的默认配置,会发现这些sh 进程有启动的过程,但是不会常驻后台,看Hudson 输 ...

  10. 安装并使用PHPunit

    安装并使用PHPunit Linux 下安装PHPunit PHP 档案包 (PHAR)  要获取 PHPUnit,最简单的方法是下载 PHPUnit 的 PHP 档案包 (PHAR),它将 PHPU ...