`
insertyou
  • 浏览: 905927 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

初探面向方面的开发(AOP)

 
阅读更多
最初接触到AOP是在什么时候我已经不记得了,大概是1年半之前。不过在这个概念出现之前,我曾经做过这样的一件事情:通过截获Remoting代理的Invoke方法来记录一些远程方法的调用和异常情况,任何时候,领域程序员写的Remoting插件里抛出的未处理异常都能被外部的截获机制自动记录,大大得方便了调试和纠错。这种把通用的错误处理和领域业务处理分开的实现方法是不是可以看作是面向了两个不同的方面呢?在牛顿发现万有引力之前,我敢肯定,苹果曾不止一次的落在了别人的头上;在AOP的概念出现之前,我也敢肯定,这方面的实践已经有相当多的人经历过。不同的,是牛顿发现了万有引力定律而不是别人;不幸的,是我至今不知道到底是谁提出了AOP的概念。谁?还有谁(冯调)...算了,不管是谁,我还是说正经的。
现在我先假想出这样的一个应用情境:一个工作流的系统起初包括了最核心功能,在不同的业务领域中,还需要为这些核心的功能加载其它的约束或者自定义功能。定义如下:
/**////<summary>
///假设的工作流引擎
///</summary>

publicclassWorkflowEngine
{
/**////<summary>
///登录到工作流系统。
///这个函数只有对登录用户的判断规则,其它变动的规则等待注入
///</summary>
///<paramname="user"></param>
///<returns></returns>

publicvirtualboolLogon(stringuser)
{

if(user=="wzcheng"||user=="xyz"||user=="*")
{
returntrue;
}

else
{
returnfalse;
}

}


/**////<summary>
///得到工作文档
///</summary>
///<paramname="user"></param>
///<paramname="docID"></param>
///<returns></returns>

publicvirtualstringGetWorkDocument(stringuser,intdocID)
{
if(this.Logon(user)&&docID>0)
return"thisisadocument!";
else
returnstring.Empty;
}


}

很容易想到的办法就是在具体的业务领域里的工作流引擎从WorkflowEngine派生并覆写它的某些方法。值得一提的是,无论是面向过程、面向对象还是面向方面的解决方案都可以达到预期的目标,不同的是对问题进行剖析的角度和实施的复杂度不同,所以下面的提到的解决方法请读者不要和OP或者OO比出一个谁优谁劣来,就如同米饭和食盐没有任何优劣可比性一样。你看我,又罗嗦了。言归正传, 首先提出问题:如果某领域的业务规则是过了中午12点就不能登录工作流系统,并且任何用户只要取文档都要被日志记录下来。从AOP的角度考虑,核心问题方面是:登录和取文档;外围问题方面是:时间约束和日志记录。核心问题是相对稳固的,外围问题是会随着用户需求的变化了变化的。

接着就是解决问题,我们可以形象的成这种办法为间谍技术、伪装技术、特使技术等等,别看我忽悠的挺夸张,不知道还以为我是国家安全局的。不过的确有点相似之处,比如某人在BBS上发帖妄言时政,他一提交就被告知:您的言论涉及敏感关键字,系统怀疑你灌水等等。你说这是什么机制,难道不是AOP吗?从BBS的角度触发,谈论面广,人气旺那是求之不得的事情,不过别忘了,大家都是生活在构造和谐社会这个大的设计框架之下,不该咱说的就别乱说嘛,就如同过了12点工作流引擎不提供服务一样,做人要厚道,不要不自觉嘛。可有些人就是不自觉,那么对这种不自觉的行为采取必要的措施不得不说是合乎天理人情的,所以AOP的应用还是有相当大的前景吧?
根据上文提到的AOP机制,我采取的做法就是采用运行时生成动态程序集的技术,放弃了平常常用new实例化对象的方式,改用类厂机制。什么是类厂呀?看官,如果这个问题还没明白的话,你得赶紧补充一下,劳驾上网查,关键字是:类厂、设计模式。我们继续,通过类厂动态实现原型类的代理类,代理类从原型类派生,按照一个需求清单覆写原型类的方法,在这些方法中添加了对其它方法的调用,我们把这种添加成为代码注入行为。对于之前提出的需求,我做了如下的实现:
/**////<summary>
///工作流的约束对象
///</summary>

publicclassWorkFlowEngineBuilder:ObjectProxy
{
staticWorkFlowEngineBuilderbuilder=newWorkFlowEngineBuilder();

publicoverrideTypeTarget
{
get{returntypeof(WorkflowEngine);}
}


publicoverrideTargetTypeTargetType
{
get{returnTargetType.Special;}
}


publicoverrideInjectCase[]OverridableList
{
get
{
InjectCase[]caseColl
=newInjectCase[2];

caseColl[
0]=newInjectCase();

/**//*向匹配Logon(*)原型的函数注入此类的Constrain函数*/

caseColl[
0].SourceInfo=this.GetType().GetMethod("Constrain");
caseColl[
0].TargetInfo=this.GetMatchMethodInfo("Logon(*)",true);

caseColl[
1]=newInjectCase();

/**//*向匹配Get(*)原型的函数注入此类的WriteLog函数*/
caseColl[
1].SourceInfo=this.GetType().GetMethod("WriteLog");
caseColl[
1].TargetInfo=this.GetMatchMethodInfo("Get*(*)",true);

/**//*注意:当多个条件命中同一函数时,系统会出错,这里等待进一步的改进*/

returncaseColl;
}

}


/**////<summary>
///过了中午12点,系统就被锁定,除非以wzcheng登录的用户
///</summary>

publicvoidConstrain()
{
stringcurrentUser=WorkFlowEngineBuilder.GetParameter<string>(0);

if(currentUser!="wzcheng")
{
if(DateTime.Now>DateTime.Parse(DateTime.Now.ToString("yyyy-MM-dd12:00")))
{
thrownewException("下班时间不能访问工作流引擎");
}

}

}


publicvoidWriteLog()
{
stringcurrentUser=WorkFlowEngineBuilder.GetParameter<string>(0);
intdocID=WorkFlowEngineBuilder.GetParameter<int>(1);
Console.WriteLine(
"{0}在{1}开始取ID为{2}文档",currentUser,DateTime.Now,docID);
}


/**////<summary>
///创建一个新的代理对象
///</summary>
///<typeparamname="T"></typeparam>
///<paramname="parameters"></param>
///<returns></returns>

publicstaticTBuildObject<T>(paramsobject[]parameters)
whereT:
class
{
returnbuilder.NewObject<T>(parameters);
}

}

客户端调用的代码如下:

WorkflowEngineworkEng=WorkFlowEngineBuilder.BuildObject<WorkflowEngine>();

try
{
boollogon=workEng.Logon(this.comboBox1.Text);
MessageBox.Show(logon
?"登录成功":"登录失败");
}

catch(Exceptionex)
{
MessageBox.Show(ex.Message);
}

从调用代码可以发现,除了用 WorkFlowEngineBuilder.BuildObject<WorkflowEngine>()代替了new WorkflowEngine() 之外没有其它的变化,但运行时可以发现,变量 workEng其实保存的是 WorkflowEngine的派生类型。这些都是表象,能说明的问题只有一个:这样的AOP实现方式在应用层还是很平滑的,不至于让程序员一开始就觉得接受不了,但这不是主要问题或者说不是主要的矛盾。是什么原因导致了AOP概念浮出水面,让G#或者aspectj取得了生存空间呢?回头我们再分析WorkFlowEngineBuilder类的如下代码:

publicoverrideTypeTarget
{
get{returntypeof(WorkflowEngine);}
}

上面的代码是指WorkFlowEngineBuilder所针对的要注入代码的目标类型,如果把 typeof(WorkflowEngine) 该成别的,WorkFlowEngineBuilder是不是就成为其它类型的注入者呢?是的。再看:

publicoverrideInjectCase[]OverridableList
{
get
{
InjectCase[]caseColl
=newInjectCase[2];

caseColl[
0]=newInjectCase();

/**//*向匹配Logon(*)原型的函数注入此类的Constrain函数*/

caseColl[
0].SourceInfo=this.GetType().GetMethod("Constrain");
caseColl[
0].TargetInfo=this.GetMatchMethodInfo("Logon(*)",true);

caseColl[
1]=newInjectCase();

/**//*向匹配Get(*)原型的函数注入此类的WriteLog函数*/
caseColl[
1].SourceInfo=this.GetType().GetMethod("WriteLog");
caseColl[
1].TargetInfo=this.GetMatchMethodInfo("Get*(*)",true);

/**//*注意:当多个条件命中同一函数时,系统会出错,这里等待进一步的改进*/

returncaseColl;
}

}

如果改写这个提供覆写清单的方法中的匹配规则,那么结合 Tagert 的改变,WorkFlowEngineBuilder是不是就完全服务于一个全新的应用场景了?那么我们平时提到的重构、复用、责任链模式等等是不是都可以在AOP的驱动下完成呢?需要提出的是:我的例子只是为了肤浅的说明一下AOP,让不了解的人有一点点了解,代码部分写的比较烂,应该没有什么借鉴之处。download source and demo / for .net 2.0.



分享到:
评论

相关推荐

    初探spring aop内部实现 java

    Spring AOP(面向切面编程)是Spring框架中的一个重要组件,它允许我们在不修改源代码的情况下,对程序的行为进行统一的管理和控制。本篇文章将深入探讨Spring AOP的内部实现,以及如何通过源代码理解其DataSource...

    pring初探共18页.pdf.zip

    Spring是Java企业级应用开发中最常用的一个框架,它以其依赖注入(Dependency Injection,简称DI)和面向切面编程(Aspect-Oriented Programming,简称AOP)为核心理念,大大简化了Java EE应用的开发工作。...

    GWT通信机制初探

    而Spring框架则常用于后端服务,提供依赖注入、AOP(面向切面编程)等功能,便于构建可维护和可扩展的系统。将两者结合,可以构建出前后端分离、结构清晰的GWT应用。 总的来说,GWT的通信机制是通过RPC服务,利用...

    Spring开发指南

    在Spring初探部分,首先涉及到的是准备工作,包括安装必要的开发环境和配置工具,为构建Spring基础代码做准备。接下来,指南会介绍Spring的基础语义,特别是依赖注入(Dependency Injection,简称DI)的概念及其在...

    spring 初探

    接下来,Spring提供了AOP(面向切面编程)支持,允许我们在不修改代码的情况下添加功能,如日志、事务管理等。AOP通过定义切面(aspect)和通知(advice)来实现,切面封装了横切关注点,而通知是在特定连接点(join...

    PAFA快速开发指南

    PAF是紫川软件推出的一款强大的应用开发框架,主要面向企业级应用开发,它提供了丰富的组件和工具,以简化开发过程,提高开发效率。阅读本指南的目标群体主要是具备Java基础,对Web应用开发有一定了解的开发者,无论...

    spring+mybatis初探

    首先,Spring框架的核心特性包括依赖注入(Dependency Injection,DI)和面向切面编程(Aspect-Oriented Programming,AOP)。依赖注入允许开发者通过配置文件或注解来管理对象间的依赖关系,从而降低了代码的耦合度...

    Java ee 企业应用开发:第7章 在Spring中管理事务.ppt

    Spring框架提供了强大的事务管理能力,通过面向切面编程(AOP)实现。AOP允许开发者将横切关注点,如日志、事务控制、安全性等,从核心业务逻辑中解耦出来。 ### 7.1 AOP简介 AOP(Aspect Oriented Programming)...

    Spring3_权威开发指南

    - **AspectJ6初探**:对AspectJ进行了初步介绍,这是一种广泛使用的面向切面编程语言。 - **老式Spring AOP**:回顾了早期版本的Spring AOP实现方式。 - **基于@AspectJ的Spring AOP**:讲解了如何使用@AspectJ...

    spring3.0中文文档

    2. **AspectJ初探与@AspectJ支持**:探索了AspectJ6的基础特性和Spring框架如何与其集成,通过`@AspectJ`注解实现AOP的高级应用。 3. **AOP配置与启用策略**:利用`&lt;aop:config/&gt;`元素进行AOP配置,通过`&lt;aop:...

    C#超酷教程

    每个HTML文件标题中的数字可能代表了教程的不同部分,例如“腾讯社区:初探c#--4.htm”可能讲解了更高级的主题,如LINQ(Language Integrated Query)或AOP(面向切面编程)。 9. **社区互动**: 通过“腾讯社区...

    spring 帮助文档

    面向切面编程(AOP)是一种编程范式,主要用于解决横切关注点(cross-cutting concerns)的问题。Spring AOP实现了基于代理(proxy-based)的AOP机制,通过代理对象拦截目标对象的方法调用并执行额外的逻辑。 **3.1.2 ...

    spring-3.1.0中文版api帮助文档

    - **AOP概述**:面向切面编程的基本原理。 - **Spring AOP基础概念**:Spring框架中的AOP实现细节。 **3.2 AspectJ 6初探** - **AspectJ介绍**:了解AspectJ 6的新特性和改进。 **3.3 老式Spring AOP** - **传统...

Global site tag (gtag.js) - Google Analytics