Spring-AOP @AspectJ进阶之绑定抛出的异常

简介: Spring-AOP @AspectJ进阶之绑定抛出的异常

概述


和通过切点函数绑定连接点信息不同,连接点抛出的异常必须使用AfterThrowing注解的throwing成员进行绑定


实例


代码已托管到Github—> https://github.com/yangshangwei/SpringMaster


aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwOTEzMDgyODQxNDQy.png


业务类

package com.xgj.aop.spring.advisor.aspectJAdvance.bindException;
import org.springframework.stereotype.Component;
@Component
public class BussinessException {
  public void dealBussiness(String bussinessName) {
    System.out.println("dealBussiness executed");
    // just a demo code ,in fact it's not cautious
    if (bussinessName != null && "bug".equals(bussinessName))
      throw new IllegalArgumentException("iae Exception");
    else
      throw new RuntimeException("re Exception");
  }
}


切面

package com.xgj.aop.spring.advisor.aspectJAdvance.bindException;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
/**
 * 
 * 
 * @ClassName: BindReturnValueAspect
 * 
 * @Description: @Aspect标注的切面,
 *               和通过切点函数绑定连接点信息不同,连接点抛出的异常必须使用AfterThrowing注解的throwing成员进行绑定
 * 
 *               (1)处throwing指定的异常名和(2)处入参的异常名相同,这个异常增强只在连接点抛出的异常instanceof
 *               IllegalArgumentException才匹配,增强方法通过iae参数可以访问抛出的异常对象。
 * 
 * @author: Mr.Yang
 * 
 * @date: 2017年9月12日 下午5:47:23
 */
@Aspect
public class BindExceptionAspect {
  // (1)
  @AfterThrowing(value = "target(com.xgj.aop.spring.advisor.aspectJAdvance.bindException.BussinessException)", throwing = "iae")
  public void crossCuttingCode(IllegalArgumentException iae) {// (2)
    System.out.println("----bindException()----");
    System.out.println("exception:" + iae.getMessage());
    System.out.println("----bindException()----");
  }
}


(1)处throwing指定的异常名和(2)处入参的异常名相同,这个异常增强只在连接点抛出的异常instanceof IllegalArgumentException才匹配,增强方法通过iae参数可以访问抛出的异常对象。


配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd
    http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
<!-- (1)声明Context命名空间以及Schema文件   (2)扫描类包以及应用注解定义的bean -->
<context:component-scan base-package="com.xgj.aop.spring.advisor.aspectJAdvance.bindException"/>
<!-- 基于@AspectJ切面的驱动器 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 使用了@AspectJ注解的切面类 -->
<bean class="com.xgj.aop.spring.advisor.aspectJAdvance.bindException.BindExceptionAspect"/>
</beans>

单元测试

package com.xgj.aop.spring.advisor.aspectJAdvance.bindException;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BindExceptionAspectTest {
  @Test
  public void test() {
    ApplicationContext ctx = new ClassPathXmlApplicationContext(
        "classpath:com/xgj/aop/spring/advisor/aspectJAdvance/bindException/conf-bindException.xml");
    ctx.getBean("bussinessException", BussinessException.class)
        .dealBussiness("bug");
  }
}


输出结果

2017-09-12 20:26:25,344  INFO [main] (AbstractApplicationContext.java:583) - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@3695de1a: startup date [Tue Sep 12 20:26:25 BOT 2017]; root of context hierarchy
2017-09-12 20:26:25,458  INFO [main] (XmlBeanDefinitionReader.java:317) - Loading XML bean definitions from class path resource [com/xgj/aop/spring/advisor/aspectJAdvance/bindException/conf-bindException.xml]
dealBussiness executed
----bindException()----
exception:iae Exception
----bindException()----


可见当sdealBussiness(“bug”)抛出异常后,异常增强起效,处理完成后,再向外抛出IllegalArgumentException。如果将①处的代码调整为dealBussiness(“bug2”)后,再运行代码,将只看到异常输出的信息,异常增强没有任何动作,这是因为RuntimeException 不按类型匹配于 IllegalArgumentException,切点不匹配。


aHR0cDovL2ltZy5ibG9nLmNzZG4ubmV0LzIwMTcwOTEzMDgzMzA2NDg2.png


总结


通过切点复合运算,你可以定义出各种复杂的切点,使切点表达式的能力进一步提升。


你可以直接使用切点复合运算符对切点函数进行运算,也可以通过切点名引用其它命名切点。


当对同一个连接点织入多个增强时,你必须考虑让切面类实现Ordered接口,此外还必须合理计划同一个切面类中增强方法的声明顺序,因为这些信息都会影响到增强的织入顺序。


在@AspectJ的切点表达式中,大多数的切点函数都可以绑定连接点方法的入参,以便增强方法访问连接点信息。


此外,你也可以简单地将增强方法的第一个入参定义为JoinPoint访问连接点的上下文。

相关文章
|
2月前
|
JSON 前端开发 Java
解决Spring MVC中No converter found for return value of type异常
在Spring MVC开发中遇到`No converter found for return value of type`异常,通常是因缺少消息转换器、返回值类型不支持或转换器优先级配置错误。解决方案包括:1) 添加对应的消息转换器,如`MappingJackson2HttpMessageConverter`;2) 自定义消息转换器并实现`HttpMessageConverter`接口,设置优先级;3) 修改返回值类型为如`ResponseEntity`的合适类型。通过这些方法可确保返回值正确转换为响应内容。
98 1
|
2月前
|
Java Spring 容器
解决Spring的UnsatisfiedDependencyException异常的方法
在Spring开发中,UnsatisfiedDependencyException异常意味着依赖注入失败,影响应用稳定性。该异常由Spring容器在无法满足bean依赖时抛出,常见原因包括bean定义错误、循环依赖、多个候选bean等。解决方法包括:检查bean定义和注入的正确性、解决循环依赖、确认依赖包的兼容性、使用@Qualifier或@Primary注解。通过日志、调试工具和异常对比来定位问题。持续学习Spring框架有助于更好地解决此类异常。
1149 1
|
2月前
|
消息中间件 监控 Java
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
Spring Boot中的RabbitMQ死信队列魔法:从异常到延迟,一网打尽【RabbitMQ实战 一】
139 0
|
2月前
|
安全 Java 开发者
深入理解Spring Boot配置绑定及其实战应用
【4月更文挑战第10天】本文详细探讨了Spring Boot中配置绑定的核心概念,并结合实战示例,展示了如何在项目中有效地使用这些技术来管理和绑定配置属性。
30 1
|
7天前
|
运维 Java 关系型数据库
Spring运维之boot项目bean属性的绑定读取与校验
Spring运维之boot项目bean属性的绑定读取与校验
13 2
|
18天前
|
Java
springboot之异常
springboot之异常
16 1
|
3天前
|
JSON Java API
如何在Spring Boot中优雅处理异常
如何在Spring Boot中优雅处理异常
|
26天前
|
前端开发 Java 程序员
SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常
SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常
|
10天前
|
Java
springboot 异常java.net.BindException: Address already in use: bind
springboot 异常java.net.BindException: Address already in use: bind
7 0
|
18天前
|
XML Java 数据格式
java异常-SpringBoot-
java异常-SpringBoot-
10 0