您的位置:首页 > 运维架构

使用AOP实现日志和权限认证组件

2010-07-19 14:51 691 查看

使用AOP实现日志和权限认证组件

技术背景:

Aspect Oriented Programming(AOP)是近来较为热门的一个话题。AOP,国内大致译作“面向方面编程”。
AOP、OOP在字面上虽然非常类似,但却是面向不同领域的两种设计思想。OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。
而AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或段,以获得逻辑过程中各部分之间低耦合性的隔离效果。这两种设计思想在目标上有着本质的差异。
上面的陈述可能过于理论化,举个简单的例子,对于“雇员”这样一个业务实体进行封装自然是OOP/OOD的任务,我们可以为其建立一个“Employee”类,并将“雇员”相关的属性和行为封装其中。而用AOP设计思想对“雇员”进行封装将无从谈起。同样,对于“权限检查”这一动作片断进行划分,则是AOP的目标领域。而通过OOD/OOP对一个动作进行封装,则有点不伦不类。换而言之,OOD/OOP面向名词领域,AOP面向动词领域。
AOP和OOD/OOP并不冲突,我们完全可以在一个应用系统中同时应用OOD/OOP和AOP设计思想,通过OOD/OOP对系统中的业务对象进行建模,同时通过AOP对实体处理过程中的阶段进行隔离处理。即使不是OOD/OOP,而是在传统的POP(面向过程编程)中,AOP也能起到同样的作用。

将不同阶段领域加以分隔,这是否就算是AOP呢?
AOP还有另外一个重要特点:源码组成无关性。
倘若应用中通过某个具体的业务逻辑类实现了独立的权限检查,而请求调度方法通过预编码调用这个权限模块实现权限管理。那么这也不算是AOP。对于AOP组件而言,很重要的一点就是源码组成无关性,所谓源码组成无关性,体现在具体设计中就是AOP组件必须与应用代码无关,简单来讲,就是应用代码可以脱离AOP组件独立编译。为了实现源码组成无关性,AOP往往通过预编译方式和运行期动态代理模式实现。考虑到使用的方便,以及本组件面对的为采用OOP设计的MIS系统,所以,我选择了使用JDK本身提供的动态代理API实现。

发明目标:

现在的数据库应用系统越来越庞大,采用多层结构,分层开发,web端的开发人员开发页面。

中间层的开发人员开发业务逻辑组件和数据访问组件。分层开发的目的在于使各个层次不相互依赖,可以独立的按照进度要求工作,这也是现在流行的所谓的软件工厂的开发思想。但真正要实现各个层次的解藕,基本上是很困难的,这跟开发人员的水平和系统的特点有关,同时,有一些通用组件比如日志和权限验证,往往在各个层次,多个组件中都要使用,这也就是Aspect(切面)的存在的原因。

按照原来的OOP的编程方式,会在代码中大量的存在调用日志,权限的代码。即使设计得很精妙,也不能实现业务组件和日志,权限组件的完全解藕,因为组件之间一旦调用就会产生藕和,而使用AOP的设计,通过Interceptor拦截事先定义好的组件中需要记录日志,需要验证权限的Action,系统自动的去作,这样业务组件就可以和权限,日志组件毫无关联,各自开发各自的,哪一端发生了变动都不影响另一端,相反,如果象过去的那样设计,一旦写日志,验证权限的方式发生变化,调用的参数有改变了,你需要修改大量的源码。产生BUG的可能性就大大的提高了。

发明内容:

因为是使用JDK的动态代理技术,所以,要求业务组件必须要有接口层,这种强制性的要求使业务组件的设计者必须使用面对对象的设计,从而使得系统有明确的抽象层和实现层之分。使用者通过调用AOPFactory,返回一个被代理的动态对象,然后通过代理对象处理业务逻辑,一旦调用业务方法,则定义好的拦截器会拦截这个action,在拦截器中会自动的对这个action进行预处理(before)和后处理(after),以及异常处理,

而权限验证针对的就是预处理,日志针对的就是后处理。这样业务组件只需要关注他自己的业务就行了,不用再考虑日志和权限了,

打个比喻,就像EJB,你只需要编写业务逻辑代码,而事务处理,安全认证这些,你都不要考虑了,统统都由EJB容器帮你去做,这里也是如此。

具体实施方式

业务组件抽象接口(强制要求使用接口定义,使得设计上更好的符合OOD)

public interface TestBusinessBase {

public void sendFile();

}
业务组件的实现

public class TestBusiness implements TestBusinessBase{

public void sendFile()

{

System.out.println("现在发送文件");

}


使用
public class Test {
public static void main(String[] args) {
Object businessProxy = AOPFactory.getAOPProxyedObject(
"aoptest.TestBusinessUser");
TestBusinessBase proxyBusiness = (TestBusinessBase) businessProxy;
proxyBusiness.sendFile();
}
}
可见,只需要在产生业务组件对象的时候调用代理工厂的方法返回一个该业务组件的代理类,就可以自动的进行权限和日志的工作了,而在业务组件TestBusiness中完成看不到有关权限和日志的代码,完全实现了组件之间的解藕。
性能上,由于JDK1.4的反射的性能已经有了很大的提高,所以利用发射产生对象的开销并不是很大。而且在一些性能要求很高的场景下,还可以使用对象池技术。使用Jmeter作压力测试,10000个并发下平均值是422毫秒。和原来的相差100毫秒以内。
http://storage.msn.com/x1pnp_rgmi5o52AXcptffT9UZS3bZ2R3QtlGlhtvS8Y1VYvAalDXhEDudsV0doKMahkdkwO1bFEZN-nM4G1PlzQ1AsUV78Da4T7L9piI6sPn0FVr2RLE7pk2Xzi1Gq1k-e7
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐