3.3. AOP应用案例(AOP Use cases)
在结束本章有关Spring AOP的话题之前,我觉得有必要从最普通的层面对适合使用AOP解决的问题场景做一简单的介绍,您愿意称其为“AOP的最佳实践
”那也未尝不可!
3.3.1. 异常处理(Exception Handling)
或许你已经在使用类似于AOP的方式对应用程序中的某些异常进行统一的处理,也或许你已经在使用AOP的方式进行异常处理,但你可能并没有意料到这实际上对应一个很有趣的概念,叫做“Fault Barrier
”,
在接触这个名词之前,笔者实际上已经将这个概念所阐述的理念应用于工作中,直到看到dev2dev上一篇《Effective Java Exception》,我才知道,原来这种异常的处理方式,还对应一个这么“有趣的
”术语。
不过,在进入“Fault Barrier
”之前,我们有必要先来回顾一下Java中的异常处理相关内容...
3.3.1.1. 异常处理简单攻略(Exception Handling Introduction)
关于异常的处理是一个很大的话题,所以,限于篇幅,我们不可能事无巨细的对异常处理的方方面面都提及,只是对Java中通常的异常类型和处理方式做一简单回顾,以便引出Fault Barrier的概念。
Java不是最早也不是唯一使用异常机制的语言,不过,Java却在引入“Checked Exception
”的基础上为其自身的异常处理添加了少许的新意。我们先来看一下Java中的异常层次体系大体上是一种什么样的结构,如下图:
在该图中,我们将java中的异常类型分为两类:
-
通常将java.lang.Error和java.lang.RuntimeException及其子类称之为“unchecked exception
”,
之所以如此称呼,是因为编译器不会对这些类型的异常进行编译期检查,因为java.lang.Error我们通常关心不着,
所以,狭义上将java.lang.RuntimeException及其子类暂且称为“unchecked exception
”我觉得也无伤大雅吧;
-
java.lang.Exception及其子类,但除去java.lang.RuntimeException分支,统称为“checked exception
”,
一旦你在程序的方法定义中声明了将会抛出“checked exception
”,调用程序便必须对这些异常进行处理,而且编译器会在编译期间对这些异常类型进行检查;
各位大师级人物对“checked exception
”和“unchecked exception
”的论战我们暂且放在一边,
不过,对于二者具体的应用场景我们有必要了解一下,毕竟基本原则还是有的,至于用好用不好那就由不得人了:
-
“unchecked exception
”通常对应系统中的严重异常情况,这些情况应用程序通常无法恢复,比如数据库挂掉,网线连接中断,服务器崩溃等等。
所以,“unchecked exception
”所提供的信息通常不是为应用程序准备的,而是为人准备的,确切的说,是为了能够让系统维护人员能够根据所提供的信息来判定到底哪里出了问题,以便人工干预;
-
“checked exception
”引入java后,一直是备受争议,不过,我觉得这跟概念本身没有任何关系,是否在应用于合适的场合是由人来决定的,而不是概念本身。
“checked exception
”通常用于表明系统中的某些罕见的非正常状态,比如,对于一个业务方法来说,使用“错误号(Error Code)
”的时代我们是通过返回-1之类数字表明一些非正常状态,
现在,我们可以通过抛出不同类型的“checked exception
”来表明这些非正常状态,并要求调用方对这些非正常状态进行处理,而编译器对“checked exception
”的检查可以进一步加强这种契约关系。
“checked exception
”通常是可恢复的,也是意料之中的,它所提供的信息是面向应用程序,而不是人,应用程序对不同的“checked exception
”类型可以根据系统逻辑有针对性的进行处理;
在《Effective Java Exception》中,作者将“unchecked exception
”对应的情况称之为“Fault
”,而将“checked exception
”对应的情况称之为“Contingency
”.
而我们的“Fault Barrier
”要处理的,就是对应Fault的情况。
对于“checked exception
”来说,不同的类型可以有不同的处理方式,这完全是由系统逻辑来决定的,调用方可以根据不同的类型,有针对性的对“checked exception
”进行处理;
反过来,对于“unchecked exception
”来说,不同的类型则是没有太多必要的,因为不管你的应用程序抛出何种类型的“unchecked exception
”,
最终都是需要人来进行干预,只要“unchecked exception
”能够提供足够的信息,相应人员就可以进行处理,完全就是无差别对待。
当系统中多个地方都可能抛出“unchecked exception
”的时候,在此之前,我们可能会在每一个调用的最顶层分别添加异常处理逻辑对其进行处理,而就像我们所说的那样,
对于“unchecked exception
”来说,实际上可以做的事情很少,通常就是记录日志,通知相应人员,所以,这些相同的逻辑实现实际上应该归并于一处进行处理,而不是让他们散落到系统的各处,也就是说,
对于系统中的Fault来说,它实际上就是一种横切关注点(Cross-cutting concern)。
鉴于此,我们完全可以实现一个对应Fault处理的Aspect,让其对系统中的所有可能的Fault情况进行统一的处理,那么,这个专职于处理Fault的Aspect,我们就可以称之为“Fault Barrier
”。
实际上,我们从讲解SpringAOP的ThrowsAdvice开始,就提供了一个“Fault Barrier
”的实现实例,在该实例中,我们通过email方式将系统中的Fault情况,也就是以“unchecked exception
”形式给出的信息转发给相关人员,并记录到日志。
当然,如果可能,你还可以加入更多的处理,比如分析“unchecked exception
”信息,为相关人员提供更加友好的系统信息等等。
Note
任何的概念都会有特例,对于异常来说也是如此,比如“unchecked exception
”也可以被相应的方法声明并被调用方捕获,不过,前面也说了,篇幅有限,无法完全囊括所有内容,
对于特殊的情况,如果后继内容有所牵扯,我们会给予相应解释。
3.3.2. 安全检查(security checking)
如果你已经Java开发web应用程序多年,那么,你一定不会对使用Filter为系统的资源访问添加控制而感到陌生吧?
javax.servlet.Filter可以算是servlet规范为我们提供的一种AOP支持,通过它,你可以为基于servlet的web应用添加相应的资源访问控制(当然,还可以做很多其他事情)。
不过,基于Filter的web应用的资源访问控制仅仅是特定领域的安全检查需求,实际上,通过AOP,你可以为任何类型的应用添加相应的安全支持。
在介绍AOP概念的时候我们就曾经提到过,安全检查属于系统的一种横切关注点,按照原先的方法进行系统开发,势必让这些安全检查逻辑散落系统各处,
所以,对付它的最好办法就是用AOP。在将系统中可能需要安全检查的点排查清楚之后,我们就可以为这些点织入安全检查的逻辑了。
要为系统中某个点添加安全支持,最简单的办法就是提供一个Interceptor,对所有访问该点的调用进行拦截。所以,对于基本的一个安全检查的Aspect实现来说,基本类似于:
@Aspect
public class SecurityAspect
{
@Around("...")
public Object doCheck(ProceedingJoinPoint pjp) throws Throwable
{
if(isIllegalRequest(pjp))
{
throw new SecurityCheckingException("necessary information");
}
return pjp.proceed();
}
}
不过,既然我们崇尚“
不重新发明轮子
”,
在动手之前,有必要google一下是否有现成的,也好免去人力物力的浪费啊。
实际上,作为基于Spring平台的一套安全框架,Acegi framework现在可以说在企业级应用的安全领域声名远扬了。
它在Spring基础之上,提供了完备的系统认证,授权,访问控制等安全检查功能。Acegi Framework最初是独立于Spring开发的,现在已经并入Spring portfolio,更名为Spring Security,
你可以在http://www.acegisecurity.org/获得有关Acegi的更多信息。
AOP应用的另一个主要场景在于为系统透明的添加缓存支持。缓存可以在很大程度上提供系统的性能,但它不属于业务需求,
而是系统需求,在现有方法论的基础之上要为系统添加缓存支持,就会因为系统中缓存需求的广泛分布,造成实现上的代码散落。
为了避免需要添加的缓存的实现逻辑污染业务逻辑的实现,我们可以让缓存的实现独立于业务对象的实现之外,将系统中的缓存需求通过AOP的Aspect进行封装,
只有当系统中某个点确切需要缓存支持的情况下,才为其织入。
使用AOP为系统添加缓存其实很简单,比如:
@Aspect
public class CachingAspect
{
private static Map cache = new LRUMap(5);
@Around("...")
public Object doCache(ProceedingJoinPoint pjp,Object key) throws Throwable
{
if(cache.containsKey(key))
{
return cache.get(key);
}
else
{
Object retValue = pjp.proceed();
cache.put(key, retValue);
return retValue;
}
}
}
我想,在没有使用AOP之前,要为系统某个地方加入缓存的话,你也是以差不多的逻辑实现的。
不过,现在我们实际上不需要这么做了:
-
现在已经有许多现成的Caching产品实现,包括EhCache,JBossCache等等;
-
Spring Extensions (Modules)项目提供了对现有Caching产品的集成,现在你可以通过外部声明的方式为系统中的Joinpoint添加Caching支持。
你可以从https://springmodules.dev.java.net/获得更多有关Spring Extensions (Modules)的信息,另外,dev2dev网站一篇
《Declarative Caching Services for Spring》
(http://dev2dev.bea.com/pub/a/2006/05/declarative-caching.html)专门介绍了如何通过Spring Cache为你的应用程序添加声明性的Caching支持。
Note
更多AOP的应用场景和最佳实践还需要您自己去挖掘,去探索...
分享到:
相关推荐
Zynaptiq 宣布用于 Mac OS X 上 AudioUnits(AU)格式的 UNVEIL 和 PITCHMAP 插件的更新现已推出。 UNVEIL 是一款实时的去混音插件,便于用户移除或隔离包括单声道在内的任意通道数量混合信号的混响声,当前最新...
图片懒加载
包括Vec2Face Unveil Human Faces from their Blackbox Features inFace Recognition论文和文献阅读报告
前端项目-unveil2,A very lightweight jQuery plugin to lazy load images
Unveil.js for Rails 在轨道上延迟加载图像。 如果您想快速使用带有rails的 ,现在可以使用它。 通过加载显示在视口中而不是加载的图像,可以提高Rails应用程序的页面速度。 安装 将Gemfile -rails gem添加到您的...
Unveil Rs是从markdown文件创建演示文稿的工具。 它的灵感来自 , 和 。 它是什么样子的 ? 观看。 安装 来自crates.io 目前,仅在提供。 首先,您需要安装rust,然后在终端中键入以下命令: cargo install ...
这意味着两次渲染将有少许性能开销,但是对于大多数应用程序来说,这不是一个大问题。 我很高兴接受PR寻求更好的解决方案。演示版安装npm install --save react-unveil用法import Unveil from 'react-unveil' ;...
unveil.js 一个非常轻量级的图片延迟加载jQuery插件
use unveil :: unveil; fn main () { let path = "public.txt" ; let contents = b"Hello world!" ; File :: create (path). unwrap (). write_all (contents). unwrap (); // Restrict filesystem view by only...
我们用手机打开淘宝触屏版首页,页面是你看到多少就加载多少,从上到下滑动加载,默认不加载。
基于系统生物学分析四物汤和四君子汤的分子特征以揭示气血的生物学基础,张莉,孙静,[目的]通过生物信息学手段分析四物汤和四君子汤的作用靶点,从而揭示中医学的气和血的潜在分子生物学机制。...
launch.js :clapper_board: 响应式Javascript演示库
in particular, our intent is to detect and unveil a possible hidden structure and regularity patterns associated with their generation mechanism. This information in turn helps our analysis and ...
Then they unveil a comprehensive Java/Ajax toolkit. Tools include JSEclipse for code editing, Venkman for JavaScript debugging, and Dojo Compressor for code compression. They also explain Log4js (and...
Delve into the internal architecture of T-SQL—and unveil the power of set-based querying—with comprehensive reference and advice from a highly regarded T-SQL expert and members of Microsoft's SQL ...
The goal of this tutorial is to progressively unveil our language, describing how it is built up over time. This will let us cover a fairly broad range of language design and LLVM-specific usage ...
Unveil the complex underpinnings of Swift to turn your app ideas into reality This book is packed with real-life examples to help you implement concepts as you learn Book Description Swift is Apple's ...
Recently the topic of how to effectively offload cellular traffic onto device-to-device (D2D) ...regarding D2D Big Data and propose to unveil a promising upcoming future of wireless D2D communications.
capacity conference room eagerly watching Microsoft’s Scott Guthrie unveil the preview version of what would later become Microsoft’s ASP MVC framework. What was shown that day would change this ...