在方法抛出异常退出时执行的通知。ApplicationContext 中在<aop:aspect> 里面使用<aop:after-throwing>元素进行声明。例如,ServiceAspect 中的returnThrow 方法。

注:可以将多个通知应用到一个目标对象上,即可以将多个切面织入到同一目标对象。

使用Spring AOP 可以基于两种方式,一种是比较方便和强大的注解方式,另一种则是中规中矩的xml配置方式。

先说注解,使用注解配置Spring AOP 总体分为两步,第一步是在xml 文件中声明激活自动扫描组件功能,同时激活自动代理功能(来测试AOP 的注解功能):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"><context:component-scan base-package="com.leon"/><context:annotation-config /></beans>

第二步是为Aspect 切面类添加注解:

/*** Annotation版Aspect切面Bean*/
//声明这是一个组件
@Component
//声明这是一个切面Bean,AnnotaionAspect是一个面,由框架实现的
@Aspect
public class AnnotaionAspect {private final static Logger log = Logger.getLogger(AnnotaionAspect.class);//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点//切点的集合,这个表达式所描述的是一个虚拟面(规则)//就是为了Annotation扫描时能够拿到注解中的内容@Pointcut("execution(* com.gupaoedu.vip.aop.service..*(..))")public void aspect(){}/** 配置前置通知,使用在方法aspect()上注册的切入点* 同时接受JoinPoint切入点对象,可以没有该参数*/@Before("aspect()")public void before(JoinPoint joinPoint){log.info("before " + joinPoint);}//配置后置通知,使用在方法aspect()上注册的切入点@After("aspect()")public void after(JoinPoint joinPoint){log.info("after " + joinPoint);}//配置环绕通知,使用在方法aspect()上注册的切入点@Around("aspect()")public void around(JoinPoint joinPoint){long start = System.currentTimeMillis();try {((ProceedingJoinPoint) joinPoint).proceed();long end = System.currentTimeMillis();log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");} catch (Throwable e) {long end = System.currentTimeMillis();log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());}}//配置后置返回通知,使用在方法aspect()上注册的切入点@AfterReturning("aspect()")public void afterReturn(JoinPoint joinPoint){log.info("afterReturn " + joinPoint);}//配置抛出异常后通知,使用在方法aspect()上注册的切入点@AfterThrowing(pointcut="aspect()", throwing="ex")public void afterThrow(JoinPoint joinPoint, Exception ex){log.info("afterThrow " + joinPoint + "\t" + ex.getMessage());}}

测试代码

@ContextConfiguration(locations = {"classpath*:application-context.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class AnnotationTest {@Autowired MemberService memberService;
//  @Autowired ApplicationContext app;@Test
//  @Ignorepublic void test(){System.out.println("=====这是一条华丽的分割线======");//      AnnotaionAspect aspect = app.getBean(AnnotaionAspect.class);
//      System.out.println(aspect);memberService.save(new Member());
//System.out.println("=====这是一条华丽的分割线======");try {memberService.delete(1L);} catch (Exception e) {//e.printStackTrace();}}}

可以看到,正如我们预期的那样,虽然我们并没有对MemberService 类包括其调用方式做任何改变,但是Spring 仍然拦截到了其中方法的调用,或许这正是AOP 的魔力所在。

再简单说一下xml 配置方式,其实也一样简单:

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-4.3.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-4.3.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd"><!-- 注解驱动加上这句话 --><!--<aop:aspectj-autoproxy proxy-target-class="true"/>--><bean id="xmlAspect" class="com.leon.vip.aop.aspect.XmlAspect"></bean><!--AOP配置 --><aop:config><!--声明一个切面,并注入切面Bean,相当于@Aspect --><aop:aspect ref="xmlAspect" ><!--配置一个切入点,相当于@Pointcut --><aop:pointcut expression="execution(* com.leon.vip.aop.service..*(..))" id="simplePointcut"/><!--配置通知,相当于@Before、@After、@AfterReturn、@Around、@AfterThrowing --><aop:before pointcut-ref="simplePointcut" method="before"/><aop:after pointcut-ref="simplePointcut" method="after"/><aop:after-returning pointcut-ref="simplePointcut" method="afterReturn"/><aop:after-throwing pointcut-ref="simplePointcut" method="afterThrow" throwing="ex"/><aop:around pointcut-ref="simplePointcut"  method="around"/></aop:aspect></aop:config></beans>

个人觉得不如注解灵活和强大,你可以不同意这个观点,但是不知道如下的代码会不会让你的想法有所改善:

/*** 获取参数Aspect切面Bean*/
//声明这是一个组件
@Component
//声明这是一个切面Bean
@Aspect
public class ArgsAspect {private final static Logger log = Logger.getLogger(ArgsAspect.class);//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点@Pointcut("execution(* com.leon.vip.aop.service..*(..))")public void aspect(){  }//配置前置通知,拦截返回值为com.leon.vip.model.Member的方法@Before("execution(com.leon.vip.model.Member com.leon.vip.aop.service..*(..))")public void beforeReturnUser(JoinPoint joinPoint){log.info("beforeReturnUser " + joinPoint);}//配置前置通知,拦截参数为com.leon.vip.model.Member的方法@Before("execution(* com.leon.vip.aop.service..*(com.leon.vip.model.Member))")public void beforeArgUser(JoinPoint joinPoint){log.info("beforeArgUser " + joinPoint);}//配置前置通知,拦截含有long类型参数的方法,并将参数值注入到当前方法的形参id中@Before("aspect()&&args(id)")public void beforeArgId(JoinPoint joinPoint, long id){log.info("beforeArgId " + joinPoint + "\tID:" + id);}}

以下是MemberService 的代码:

/*** 注解版业务操作类*/
@Service
public class MemberService {private final static Logger log = Logger.getLogger(AnnotaionAspect.class);public Member get(long id){log.info("getMemberById method . . .");return new Member();}public Member get(){log.info("getMember method . . .");return new Member();}public void save(Member member){log.info("save member method . . .");}public boolean delete(long id) throws Exception{log.info("delete method . . .");throw new Exception("spring aop ThrowAdvice演示");}}

应该说学习Spring AOP 有两个难点,第一点在于理解AOP 的理念和相关概念,第二点在于灵活掌握和使用切入点表达式。概念的理解通常不在一朝一夕,慢慢浸泡的时间长了,自然就明白了,下面我们简单地介绍一下切入点表达式的配置规则吧。通常情况下,表达式中使用”execution“就可以满足大部分的要求。表达式格式如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
throws-pattern?

modifiers-pattern:方法的操作权限

ret-type-pattern:返回值

declaring-type-pattern:方法所在的包

name-pattern:方法名

parm-pattern:参数名

throws-pattern:异常

其中, 除ret-type-pattern 和name-pattern 之外, 其他都是可选的。上例中, execution(*com.spring.service.*.*(..))表示com.spring.service 包下,返回值为任意类型;方法名任意;参数不作限制的所有方法。

最后说一下通知参数,可以通过args 来绑定参数,这样就可以在通知(Advice)中访问具体参数了。

例如,<aop:aspect>配置如下:

<aop:config><aop:aspect ref="xmlAspect"><aop:pointcut id="simplePointcut"expression="execution(* com.leon.aop.service..*(..)) and args(msg,..)" /><aop:after pointcut-ref="simplePointcut" Method="after"/></aop:aspect>
</aop:config>

上面的代码args(msg,..)是指将切入点方法上的第一个String 类型参数添加到参数名为msg 的通知的入参上,这样就可以直接使用该参数啦。

在上面的Aspect 切面Bean 中已经看到了,每个通知方法第一个参数都是JoinPoint。其实,在Spring中,任何通知(Advice)方法都可以将第一个参数定义为org.aspectj.lang.JoinPoint 类型用以接受当前连接点对象。JoinPoint 接口提供了一系列有用的方法, 比如getArgs() (返回方法参数)、getThis() (返回代理对象)、getTarget() (返回目标)、getSignature() (返回正在被通知的方法相关信息)和toString() (打印出正在被通知的方法的有用信息)。

异常通知(After Throwing Advice)相关推荐

  1. Spring AOP 中 advice 的四种类型 before after throwing advice around

    Spring  AOP(Aspect-oriented programming) 是用于切面编程,简单的来说:AOP相当于一个拦截器,去拦截一些处理,例如:当一个方法执行的时候,Spring 能够拦截 ...

  2. spring23:Aspectj实现异常通知@AfterThrowing

    切入类: package com.atChina.Test4;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Proceeding ...

  3. 返回通知异常通知环绕通知

    [返回通知] LoggingAspect.java: 1 @Aspect 2 @Component 3 public class LoggingAspect { 4 /* 5 * 在方法正常执行后执行 ...

  4. spring-AspectJ异常通知

    一.创建项目     项目名称:spring101002 二.添加jar包     1.在项目中创建lib目录         /lib     2.在lib目录下添加相关spring jar包    ...

  5. spring之aop(前置通知,后置通知,环绕通知,过滤通知,异常通知)

    1.AOP中关键性概念  连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出 目标(Target):被通知(被代理)的对象 注1:完成具体的业务逻辑 通知(Advice ...

  6. Spring Boot AOP面向切面编程使用(定义切入点、前置通知、后置通知、返回通知、异常通知、环绕通知)

    1 AOP AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发 ...

  7. spring之AOP(面向切面编程)和五大通知(前置通知、后置通知、异常通知、环绕通知、过滤通知)

    一.aop的介绍 1.AOP中关键性概念 : 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出. 目标(Target):被通知(被代理)的对象 注1:完成具体的业务逻 ...

  8. 配置切入点表达式|| 前置通知、后置通知、异常通知、最终通知、环绕通知

    环绕通知 pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo ...

  9. laravel 控制器中使用中间件_在 Laravel 中使用 Slack 进行异常通知

    php中文网最新课程 每日17点准时技术干货分享 异常处理是软件开发过程中无法逃避的问题.对于一套设计良好代码高效的程序,出现异常的可能性会比较低,但这并不意味着不会出现异常,有些异常甚至会引起严重的 ...

  10. springboot集成钉钉_用于spring boot基于钉钉的异常通知

    前言 作为后端开发者,项目上线之后难免会遇到各种问题,一个良好且及时的异常通知机制可以让我们在项目的维护上避免很多不必要的麻烦. 本项目的开发愿景是为了给使用者在线上项目的问题排查方面能够带来帮助,简 ...

最新文章

  1. 第八周项目四-角色有多样武器
  2. datatable 导入mysql 解决_将DataTable中的数据导入到数据库中
  3. ios越狱系统UIGestureRecognizer事件截获问题
  4. 帅帅什么意思_为什么99%的花艺师都害怕创作?
  5. [2013.9.27][cpp]一个简单的链接栈模型
  6. xp本地服务器虚拟目录创建,WindowsXp系统怎么创建虚拟目录
  7. python3 用递归方法列出所有目录与文件
  8. 计算机视觉应用培训心得体会,三维计算机视觉学习感想
  9. spss数据的预处理
  10. GIS中常用专业英文术语
  11. Docker端口映射后,外机访问不了的问题
  12. 跨平台,开源,免费的单片机IDE开发环境搭建-SDCC+eclipse
  13. USB总线虚拟示波器,用高性能硬件模块,组合成多种仪器
  14. 运维工程师发展受限,那么运维转型大数据是个机会吗?
  15. 联想微型计算机供电电源线,拆修一只联想电源适配器,告诉你一个不为人知的秘密...
  16. 睡不着听什么音乐睡得快,失眠入睡音乐歌单推荐
  17. 微信小程序聊天室 前后端源码附效果图和数据库结构图
  18. FileZilla Server报错Could not load TLS libraries 的解决方法
  19. c++ 定义一个字符栈类Stack(包括类的实现)。数据成员包括一个存放字符的数组stck[ ]和一个栈指针tos。栈数组的尺寸由常量SIZE确定。栈的基本操作为Push()和Pop()。
  20. 调整oracle服务器时间,oracle数据库因一次服务器时间调整引发的实例宕机注意事项及解决方案...

热门文章

  1. Git 添加到Git 仓库
  2. XML 序列化与反序列化
  3. thinkPHP增删改查的方法案例
  4. Two-stage rotation animation is deprecated. This application should use the smoother single-stage an
  5. javascript技巧及常用事件方法集合(全)
  6. IE6下position:absolute的定位BUG(转载)
  7. Javadoc的使用
  8. 大型网站典型故障案例分析
  9. JavaScript实现表单的分向提交
  10. JSP学习总结:2006