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 是一款实时的去混音插件,便于用户移除或隔离包括单声道在内的任意通道数量混合信号的混响声,当前最新...
图片懒加载
在实际应用中,unveil2的使用相当简单。首先,需要在HTML中引入jQuery库和unveil2插件的脚本文件。然后,只需要给需要进行懒加载的图片元素添加特定的类名(通常是"data-src"或"data-unveil"),并设置真正的图片源...
包括Vec2Face Unveil Human Faces from their Blackbox Features inFace Recognition论文和文献阅读报告
2. **回调函数**:unveil.js 提供了一个`load`事件,可以在图片加载完成后执行自定义操作,如调整图片大小或应用滤镜。 **总结** unveil.js 是一个优秀的图片延迟加载解决方案,适用于各种类型的网站和项目。它的轻...
Unveil.js for Rails 在轨道上延迟加载图像。 如果您想快速使用带有rails的 ,现在可以使用它。 通过加载显示在视口中而不是加载的图像,可以提高Rails应用程序的页面速度。 安装 将Gemfile -rails gem添加到您的...
在unveil-master这个项目中,很可能包含了一个实现滑动加载的示例代码或框架,包括JavaScript文件、CSS样式表和可能的HTML模板。通过研究这些文件,开发者可以学习如何在自己的项目中实现滑动加载功能,提升网页性能...
Unveil Rs是从markdown文件创建演示文稿的工具。 它的灵感来自 , 和 。 它是什么样子的 ? 观看。 安装 来自crates.io 目前,仅在提供。 首先,您需要安装rust,然后在终端中键入以下命令: cargo install ...
"unveil:响应式Javascript演示库"是一个专注于创建响应式和交互式演示的JavaScript库。这个库的主要目标是帮助开发者和设计师制作出引人入胜、适应不同屏幕尺寸的在线内容展示。通过使用unveil,你可以创建出在桌面...
这意味着两次渲染将有少许性能开销,但是对于大多数应用程序来说,这不是一个大问题。 我很高兴接受PR寻求更好的解决方案。演示版安装npm install --save react-unveil用法import Unveil from 'react-unveil' ;...
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...
使用方法通常包括引入jQuery库(如`jquery-1.9.1.min.js`)和unveil插件,然后对需要延迟加载的图片应用特定的CSS类或者属性,让插件识别并处理它们。 例如,在HTML代码中,我们可能会为图片设置一个低分辨率的占位...
在这个案例中,它可能记录了 `jquery.unveil.js` 的依赖和版本信息,方便项目管理和更新。 ### 六、实践与优化 1. **图片预加载**:对于重要的首屏图片,可以考虑预加载,确保用户打开页面时能立即看到。 2. **...
jQuery是一款广泛应用于Web开发的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画设计和Ajax交互。本资源包含上千个jQuery的常用插件,这些插件为开发者提供了丰富的功能选择,以满足不同项目的...
jQuery是一款广泛应用于Web开发的JavaScript库,它极大地简化了JavaScript的DOM操作、事件处理、动画设计和Ajax交互。"Jquery特效插件集合"显然是一份包含多种jQuery特效插件的资源包,对于Web开发者来说,这些插件...
在这个课程中,学生还可以学习到许多计算机专业英语的词汇和短语,如brilliant、distinguish、quantum、mechanics、reside、unveil、rewire、delve、predecessor、successor、synonymous等。这些词汇和短语都是...
8. **源码分析**:对于“unveil-master”这样的项目,它可能是一个名为“Unveil”的延迟加载插件的源代码。分析源码可以帮助我们理解其工作原理,学习如何实现类似功能,以及如何根据需求进行定制。 9. **工具集成*...
在IT行业中,JavaScript(简称JS)是一种广泛应用于前端开发的编程语言,它的灵活性和功能强大使其成为创建交互式网页和动态效果的首选工具。今天我们要探讨的是如何利用JS实现震撼的图片展示效果,这对于网站设计和...
此外,jQuery插件如`jQuery.lazyLoad`或`Unveil.js`提供了一种延迟加载图片的方法,只有当图片进入视口时才会开始加载,这进一步优化了性能,尤其是对于有大量图片的页面。 在处理图片资源时,我们还需要考虑到响应...