自己实现简单的AOP(二)引入Attribute 为方法指定增强对象
话续前文 : 自己实现简单的AOP(一)简介
在前一篇文章中,对AOP的实现方式做了一个简单介绍。接下来,引入Attribute 为方法指定增强对象,由此实现一个简单的AOP。
注意:指定的是增强对象,“对象”,也就是说Attribute标记,标记的其实是一个对象。由此、使用多态便可轻松实现增强的扩展。
自定义的Attribute
/// <summary>
/// 为方法标记指定的增强对象
/// <para>指定的增强,可通过代理 DelayProxy 织入</para>
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
public sealed class AdviceAttribute : Attribute
{
/// <summary>
/// 增强对象
/// </summary>
public AdviceAbstract Advice { get; private set; } /// <summary>
/// 使用指定类型的默认增强对象
/// <para>如果类型为空 则不使用任何增强</para>
/// </summary>
/// <param name="type"></param>
public AdviceAttribute(Type type)
: this(type, string.Empty)
{ } /// <summary>
/// 使用公有静态方法名初始化指定类型的增强对象
/// <para>如果类型为空 则不使用任何增强</para>
/// </summary>
/// <param name="type">类型</param>
/// <param name="methodName">
/// 公有静态方法名
/// <para>如果方法名为空,调用默认构造函数</para>
/// </param>
public AdviceAttribute(Type type, string methodName)
{
// 如果类型为空 则不使用任何增强
if (type == null)
{
this.Advice = null;
return;
} if (string.IsNullOrWhiteSpace(methodName))
{
this.Advice = Activator.CreateInstance(type) as AdviceAbstract;
return;
} this.Advice = type.InvokeMember(
methodName,
System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Static,
null, null, null) as AdviceAbstract;
} #region 以下两种方式效果不是很好,不推荐使用,故 构造函数私有化 /// <summary>
/// 使用参数列表初始化指定类型的增强对象
/// </summary>
/// <param name="type">类型</param>
/// <param name="objs">参数列表</param>
private AdviceAttribute(Type type, params object[] objs)
{
this.Advice = Activator.CreateInstance(type, objs) as AdviceAbstract;
} /// <summary>
/// 使用命名参数初始化指定类型的增强对象
/// </summary>
/// <param name="namedParameter">
/// 以 冒号 和 分号 分割的形参的命名参数列表
/// <para>支持的数据类型有:string, int, bool 及 可通过静态方法Parse 反序列化的类型</para>
/// </param>
/// <param name="type"></param>
private AdviceAttribute(string namedParameter, Type type)
{
this.Advice = ReflectionUtil.InvokeConstructor(type, namedParameter) as AdviceAbstract;
} #endregion }
Attribute
增强的抽象类 和 自定义的增强
/// <summary>
/// 抽象的增强类
/// </summary>
public abstract class AdviceAbstract
{
public abstract IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage);
} public class MyAdvice : AdviceAbstract
{
public override IMessage Invoke(MarshalByRefObject target, IMethodCallMessage callMessage)
{
this.BeforeInvoke(target); IMessage message = DelayProxyUtil.InvokeBeProxy(target, callMessage); this.AfterInvoke(target); return message;
} protected virtual void BeforeInvoke(MarshalByRefObject target)
{
Console.WriteLine("Before");
} protected virtual void AfterInvoke(MarshalByRefObject target)
{
Console.WriteLine("After");
} }
Advice
有了如上的两个组件,再借助代理类 DelayProxy<T>,将增强织入,简单的AOP就已经初具原形了。
/// <summary>
/// 支持泛型、支持延迟初始化的代理类, 可为 MarshalByRefObject 的子类型提供代理
/// <para>在执行代理的过程中,获取 AdviceAttribute 所指定的增强,并织入该增强</para>
/// </summary>
public class DelayProxy<T> : RealProxy where T : MarshalByRefObject
{
private static object objLock = new object(); /// <summary>
/// 被代理的对象
/// </summary>
private T target; /// <summary>
/// 是否延迟初始化
/// <para>True:延迟, False: 不延迟</para>
/// </summary>
private readonly bool delay; public DelayProxy(T target, bool delay)
: base(typeof(T))
{
this.target = target;
this.delay = delay;
} /// <summary>
/// 调用被代理对象
/// <para>支持 out ref 参数</para>
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public override IMessage Invoke(IMessage msg)
{
if (this.delay && this.target == null)
{
lock (objLock)
{
if (this.delay && this.target == null)
{
T instance = Activator.CreateInstance(typeof(T)) as T; // 自动装配属性
// 为属性对象启用代理,并延迟初始化被代理的对象
// DelayProxyUtil.AutowiredProperties(instance); this.target = instance;
}
}
} IMethodCallMessage callMessage = (IMethodCallMessage)msg; AdviceAttribute attri = ReflectionUtil.GetCustomAttribute<AdviceAttribute>(callMessage.MethodBase); if (attri != null && attri.Advice != null)
{
return attri.Advice.Invoke(this.target, callMessage);
} return DelayProxyUtil.InvokeBeProxy(this.target, callMessage);
} }
DelayProxy
附源码(MVC4的项目 没有packages文件夹):http://files.cnblogs.com/files/08shiyan/AOPDemo.zip
该源码中还实现了被代理对象的延迟初始化。
未完待续...
自己实现简单的AOP(二)引入Attribute 为方法指定增强对象的更多相关文章
- 自己实现简单的AOP(一)简介
AOP 和 OOP,在我看来是两种相辅相成的技术,作为OOP的补充,AOP 有着自己特殊的应用场景. 假设,我们需要在Service层实现以下几项基本功能: /// <para>1.自动管 ...
- aop学习总结二------使用cglib动态代理简单实现aop功能
aop学习总结二------使用cglib动态代理简单实现aop功能 模拟业务需求: 1.拦截所有业务方法 2.判断用户是否有权限,有权限就允许用户执行业务方法,无权限不允许用户执行业务方法 (判断是 ...
- 从Unity中的Attribute到AOP(二)
上一篇文章我们初步了解了一下Attributes的含义,并且使用系统自带的Attributes写了点代码.在进一步解剖我们的代码之前,我觉得有个概念可能需要巩固一下:什么是元数据? 我们知道C#代码会 ...
- 动手造轮子:实现一个简单的 AOP 框架
动手造轮子:实现一个简单的 AOP 框架 Intro 最近实现了一个 AOP 框架 -- FluentAspects,API 基本稳定了,写篇文章分享一下这个 AOP 框架的设计. 整体设计 概览 I ...
- 自己实现简单的AOP(三) 实现增强四项基本功能
前面的两篇随笔,都是只是个铺垫,真正实现增强四项基本功能的重头戏,在本篇随笔中, 本文将通过AOP实现如下的四个基本功能: /// <para>1.自动管理数据库连接[可选]</pa ...
- 自己实现简单的AOP(四)自动初始化代理对象
前面三篇随笔,已经完成了AOP的核心功能,但 代理对象的初始化还是有些麻烦,本文将解决该问题. Demo 片段如下: public class HomeController : Controller ...
- spring---aop(9)---Spring AOP中引入增强
写在前面 Spring将introduction通知看作一种特殊类型的拦截通知.用Spring的行话来讲,对方法的增强叫做Wearing(织入),而对类的增强叫introduction(引入).Int ...
- 从头认识Spring-3.1 简单的AOP日志实现-某方法之前的前后记录日志
这一章节我们引入简单的AOP日志实现. 1.domain 蛋糕类: package com.raylee.my_new_spring.my_new_spring.ch03.topic_1_1; pub ...
- 从头认识Spring-3.4 简单的AOP日志实现-扩展添加检查订单功能,以便记录并检測输入的參数
这一章节我们再上一个章节的基础上加上一个检查订单功能 1.domain 蛋糕类: package com.raylee.my_new_spring.my_new_spring.ch03.topic_1 ...
随机推荐
- Call for Papers International Conference for Smart Health (ICSH) 2014
Call for PapersInternational Conference for Smart Health (ICSH) 2014 Beijing, China July 10-11, 2014 ...
- Hibernate 延迟加载原理
如何简单的理解延迟加载?开发中常见的org.hibernate.LazyInitializationException no session错误又是怎么产生的?下面通过一个简单的例子来解析一下 ...
- 跨域获取json一些理解[腾讯电商数据的拉取方式]
如何跨域获取json数据源?我们都知道要有callback,具体callback是如何工作的呢?如果服务器端不接收callback,我们是不是就没有办法处理了呢?读完本文后相信你会有一个大体的了解. ...
- ie a absolute bug
给a设置position:absolute时,在IE下,尽管display:block;width:100%;height:100%,依然无法点击.但是加一个背景颜色就可以了.如果不需要背景,再把背景 ...
- Go语言实战 - 创业进行时之创业伊始
在工作了10年之后,我于32岁的年纪在两个月前辞职创业了. 简单介绍一下之前的整个职业生涯,挺典型的,工程师 –> 资深工程师 –> 架构师 –> 项目经理 –> 部门经理,可 ...
- Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里
<Windows Azure Platform 系列文章目录> Azure SQL Database (19) Stretch Database 概览 Azure SQL Da ...
- 【Prince2是什么】PRINCE2认证之项目四大管理步骤
昨天谈到PRINCE2要求项目经理在做项目的时候要考虑四大核心指标(成本.时间.质量.范围)加风险与收益这两个重要要素. 然后PRINCE2基于这几大要素进行了四大管理步骤,分别是: 1.计划 2.授 ...
- 创建分区表和查看分区表的Metadata
未分区的表,只能存储在一个FileGroup中:对table进行分区后,每一个分区都存储在一个FileGroup中.表分区是将逻辑上一个完整的表,按照特定的字段拆分成Partition set,分散到 ...
- ExecuteReader在执行有输出参数的存储过程时拿不到输出参数
异常处理汇总-后端系列 http://www.cnblogs.com/dunitian/p/4523006.html 后期会在博客首发更新:http://dnt.dkill.net/Article/D ...
- UITableView 一直显示滚动条(ScrollBar Indicators)、滚动条Width(宽度)、滚动条Color(颜色)
在 IOS 中,对 UIScrollView 的滚动条(ScrollBar Indicators)的自定义设置接口,一直都是很少的.除了能自定义简单的样式(UIScrollViewIndicatorS ...