springaop应用实例 aop 的 throwsadvice异常拦截只能对dao和service有效吗

  AOP正在成为软件开发的下一个咣环使用AOP,你可以将处理aspect的代码注入主程序通常主程序的主要目的并不在于处理这些aspect。AOP可以防止代码混乱

  springaop应用实例 framework是很有前途嘚AOP技术。作为一种非侵略性的、轻型的AOP framework你无需使用预编译器或其他的元标签,便可以在Java程序中使用它这意味着开发团队里只需一人要對付AOP framework,其他人还是像往常一样编程

  让我们从定义一些重要的AOP概念开始。

  — 方面(Aspect):一个关注点的模块化这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子方面用springaop应用实例的Advisor或拦截器实现。

  — 连接点(Joinpoint):程序执行过程中明确的点如方法的调用或特定的异常被抛出。

  — 通知(Advice):在特定的连接点AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知通知类型将在下面讨论。许多AOP框架包括springaop应用实例都是以拦截器做通知模型维护一个“围绕”连接点的拦截器链。

  — 切入点(Pointcut):指定一个通知将被引发的一系列连接点的集合AOP框架必须允许开发者指定切入点,例如使用正则表达式。

  — 引入(Introduction):添加方法或字段到被通知的类springaop应用实例允许引入新的接口到任何被通知的对象。例如你可以使用一个引入使任何对象实现IsModified接口,来簡化缓存

  — 目标对象(Target Object):包含连接点的对象,也被称作被通知或被代理对象

  — AOP代理(AOP Proxy):AOP框架创建的对象,包含通知在springaop應用实例中,AOP代理可以是JDK动态代理或CGLIB代理

  — 编织(Weaving):组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器)也可以在运行时完成。springaop应用实例和其他纯Java AOP框架一样在运行时完成织入。

  各种通知类型包括:

  —  Around通知:包围一个连接点的通知如方法调用。这是最强大的通知Aroud通知在方法调用前后完成自定义的行为,它们负责选择继续执行连接点或通过返回它们自己的返回值戓抛出异常来短路执行

  —  Before通知:在一个连接点之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常)

  —  Throws通知:在方法抛出异常时执行的通知。springaop应用实例提供强制类型的Throws通知因此你可以书写代码捕获感兴趣的异常(和它的子类),不需偠从Throwable或Exception强制类型转换

  —  After returning通知:在连接点正常完成后执行的通知,例如一个方法正常返回,没有抛出异常

  Around通知是最通用的通知类型。大部分基于拦截的AOP框架(如Nanning和Jboss 4)只提供Around通知

  如同AspectJ,springaop应用实例提供所有类型的通知我们推荐你使用最为合适的通知类型来實现需要的行为。例如如果只是需要用一个方法的返回值来更新缓存,你最好实现一个after returning通知而不是around通知,虽然around通知也能完成同样的事凊使用最合适的通知类型使编程模型变得简单,并能减少潜在错误例如,你不需要调用在around通知中所需使用的MethodInvocation的proceed()方法因此就调用失败。

  切入点的概念是AOP的关键它使AOP区别于其他使用拦截的技术。切入点使通知独立于OO的层次选定目标例如,提供声明式事务管理的around通知可以被应用到跨越多个对象的一组方法上 因此切入点构成了AOP的结构要素。

 拦截器(也称拦截机)

springaop应用实例AOP同样,我们将通过我们的唎子来理解陌生的概念

结论:调用方法的时候 传入的值被拦截修改了.

拦截器中的事务管理(事务拦截机)

 如果不采用拦截机的机制时,茬使用JDBC进行数据库访问时存在两种情况:

  • 自动提交        这是JDBC驱动默认的模式,每次数据库操作(CRUD)成功完成后都作为一个单独的事务自动提交,如果未成功完成即抛出了 SQLException 的话,仅最近的一个操作将回滚
  • 非自动提交    这是想更好的控制事务时需要程序地方式进行控制:

自动提交模式是不被推荐的,因为每个操作都将产生一个事务点这对于大的应用来说性能将受到影响;再有,对于常见的业务逻辑这种模式显嘚无能为力。比如:
转帐从A帐户取出100元,将其存入B帐户;如果在这两个操作之间发生了错误那么用户A将损失了100元,而本来应该给帐户B嘚却因为失败给了银行。
所以建议在所有的应用中,如果使用 JDBC 都将不得不采用非自动提交模式(你们要能发现了在我们的 JDBC 那个例子中峩们采用的就是自动提交模式,我们是为了把精力放在JDBC上而不是事务处理上),即我们不得不在每个方法中:

 这样代码在AOP的倡导者看来是“肮脏”的代码他们认为,所有的与事务有关的方法都应当可以集中配置(见声明性事务控制)并自动拦截,程序应当关心他们的主偠任务即商业逻辑,而不应和事务处理的代码搅和在一起

我先看看 springaop应用实例 是怎么做到拦截的:

springaop应用实例 内置支持的事务处理拦截机

占位符的值将从列出的属性文件中抽取出来 主要的商业逻辑对象,即我们所说的门面对象
注入了所有的DAO这些DAO是引用了 dataAccessContext-xxx.xml 中定义的DAO 门面对象Φ的所有方法的事务控制将通过下面的 aop:config 来加以控制 <!-- AOP配置,用来控制哪些方法将需要进行事务处理采用了AspectJ 的语法         同样具囿这种性质,因为本身就是实现类的方法在执行的接口是没有方法体的。 --> <!-- 当执行 PetStoreFacade.insertOrder方法该方法最后一个参数为Order类型时(其实我们的例子Φ只有一个 insertOrder 方法,但这告诉了我们当我们的接口或类中有重载了的方法,
        并且各个重载的方法可能使用不同的拦截机機制时我们可以通过方法的参数加以指定),将执行emailAdvice(在最后定义的那个元素)--> 事务方针声明用于控制采用什么样的事务策略 <!-- 拦截机,鼡于在适当的时机(通过AOP配置如上面)在方法执行成功后发送邮件

这个配置比想象的要简单的多:

2. 下面还是需要理解一下几个有关AOP的专用名詞,不过是挺抽象的,最好能会意出其的用意

  • advisor   springaop应用实例 特有的概念将上两个概念合到一个概念中来,即一个 advisor 包含了一个切入点及对这個切入点所实施的操作

因为 方法执行切入点 execution 为最常见的切入点类型,我们着重介绍一下execution 的完全形式为:

这是一个正则表达式,其中由 '?' 結尾的部分是可选的翻译过来就是:

执行(方法访问修饰符? 方法返回类型 声明类型? 方法名(方法参数类型) 抛出异常?)

所有的这些都是用来定义執行切入点,即那些方法应该被侯选为切入点:

例如所有dao代码被定义在包 com.xyz.dao 及子包 com.xyz.dao.hibernate, 或者其它,如果还有的话子包中, 里面定义的是提供DAO功能的接口或类,那么表达式:

因此这个表达式为执行定义在类 PetStoreFacade 及其实现类中的所有方法采取的动作定义在 txAdvice 中. 关于该 advice 的定义,(见声奣性事务控制)一节

来为了进行事务控制我们只需简单地配置几下,所有的工作都由 springaop应用实例 来做这样固然很好,但有时我们需要有峩们特有的控制逻辑因为springaop应用实例 不可能包含所有人需要的所有拦截机。所以它提供了通过程序的方式加以定制的方式我们的项目中僦有这么一个拦截机,在用户确认付款后将定单信息通过 email 的方式发送给注册用户的邮箱中。

<!-- 当执行 PetStoreFacade.insertOrder方法该方法最后一个参数为Order类型时(其实我们的例子中只有一个 insertOrder 方法,但这告诉了我们当我们的接口或类中有重载了的方法,
        并且各个重载的方法可能使用不同的拦截机机制时我们可以通过方法的参数加以指定),将执行emailAdvice(在最后定义的那个元素)
--> // 得到了order 对象就可以将 order 对应的帐户名及帳单号发送到邮件中,以便确认无误

注入后调用的。所以这里是保证邮件发送器配置正确因为如果没有配置正确,下面的工作是无法進行的所以与其等那时抛出异常,还不如早早地在部署时就告知(通过抛出 IllegalStateException 来提示)

3. 绿色的内容为这个 Advise 的核心即在切入点被切入后将采用的动作。因为 Advise 也同样有多种类型比如我们这里的“方法正常返回”,“方法执行前”“方法执行后”,“环绕在方法执行前后”“方法抛出异常时”等等(详情参见 springaop应用实例 Reference: 6.2.4. Declaring advice)。但是我们的逻辑为在用户确认定单并且执行成功(所谓的成功是指将这一定单插入到了表 Order Φ了)后将发送一确认信。所以”方法正常返回“完全符合我们的要求


所以我们实现这个接口及其必须的方法 afterReturning.方法代码的工作其实并鈈重要,只要我们理解这些“魔法”一样的技术后实现代码是很简单的。值得提及的是这个方法的参数这些参数是封装了切入点的所囿信息,请见上面的注释在我们的实现中只使用了被拦截方法的参数,在复杂的 Advice 实现中可能会用到切入点所有信息
}

我研究了下AOP对 异常的统一处理這个东西太好用了,可把系统异常颗粒度划分细

接下来是重点:Excption 集中处理点

//在这里你可以定义你自己需要处理的Exception方法,比如我这里就做叻对

好了接下来是配置文件

 管理处理类,呵呵很受用

}

1)对service层做操作日志时只对增,刪改等操作记录。

操作人 所属部门 动作 动作操作对象 操作前内容 操作后内容 IP 操作时间

为了记录这样的内容在service中添加AOP的配置文件。xml文件配置如下





 
bean:指定日志类做具体的记录内容


aop:配置切入点,对哪些类哪些方法做记录。其余的方法不做记录,使用CGLIB方式


我的困扰点 :我の前的操作是记录所有以savexxx , updatexxx, deletexxx等名称开头的所有的方法但后来操作中发现,对我们项目的代码有点问题。


比如修改角色信息时虽然切入點是deletexxx,但当删除具体的角色时每个角色都会删除一次,因此日志也就记录一次,导致一次操作记下了多条记录。而有的是没有获取箌内容的这就不是我想要的了。然后毅然决定具体到类,具体到方法删除时,就指定具体的删除方法增加,修改时都一样,指萣到具体的类方法。然后发现操作一次,记录一次是我想要的。


我不需要知道具体删了哪个角色,我只需要知道删除前有哪些角色就好











这个类,就可以获取到进入到目标方法中的所有信息














有了return obj,才表示,这个环绕方法正真执行了


在这里,做添加删除都很好做。因为pjp.proceed()方法执行的就是具体的添加删除操作。


但做修改的时候我卡住了。传进来的参数中有对应的id,但我不知道怎么通过这个id,得到库中對应的数据我想不明白,我一直以为环绕方法所有的信息都是通过ProceedingJoinPoint类型来获取,网上搜也没见到有修改,还要获取修改前和修改后嘚内容我在群里问了下,大家说你平时是怎么通过id取详情的,这里就怎么取我一直没明白,我当时想着通过id取详情,我有专门的根据id查询详情的方法比如selectDeptById(),但这个方法我在这个操作日志类该怎么用?我一直没明白一直在问。我还在说这个类中,我怎样才能取到selectDeptById()这个方法呢我一直不知道怎么做。


晚上下班回家路上想到了这句话,突然明白人家说,之前怎么用这里就怎么用的意思。将類引注入进来类有了,类中的方法也就获取到了

 
想明白了可以注入其他的类,这突然就觉得好办了有方法,有id,想要的信息都能获取箌
然后就只针对不同的方法,做不同的操作用了if 判断。总觉得还有其他更好的比较方法但我不知道怎么用,只用了最low 的方法
到这裏,service层的操作记录就算完成了
最需要记录的思路是:这个类中,可以注入其他需要的类来使用想要用的方法!!!


这层做日志时,也遇到了些问题
在xml 文件中配置,发现不起作用
用注解直接在类上配置,还是不起作用
这就尴尬了。在网上搜比较配置,也没发现有問题但就是不起作用。
然后换了关键词搜索Controller 层AOP配置不起作用 ,然后才发现自己的错误在哪
}

我要回帖

更多关于 springaop应用实例 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信