`

【Java】AOP使用示例 之 统一异常处理

 
阅读更多

本文将使用 Spring AOP 提供一个关于统一异常处理的 AOP 技术应用示例。

(可直接跳到 2.2 查看代码示例:Maven依赖 + 切面类 + Bean配置)

 

1. AOP简述

AOP 全称为“Aspect Oriented Programming”,中文译名为“面向切面编程”。乍一看非常令人费解。但是你真正理解这项技术(或者说这个思想)要做什么后,你又会觉得“切面”(Aspect)这个词还真有些贴切。“切面”指的是这项技术(AOP)的控制代码并不是直接与业务代码结合在一起;而是分开编写,再由AOP技术根据控制代码中(对目标业务代码)的描述将两者结合在一起。如果我们把“控制代码与业务代码直接编写在一起”称为“正面操作”,那么AOP技术的方式可以称为“侧面操作”或“切面操作”,也就是“面向切面编程”。

 

AOP 可以被看作是 OOP 的一个补充。面向对象编程的模式对于跨越不同对象或类的逻辑处理能力有限。AOP的动态代理机制可以大幅提高代码的抽象程度和复用度。



 

 

AOP结合控制代码与业务代码的模式有“编译时结合”与“运行时结合”。

本示例中所使用的Spring AOP技术属于运行时结合模式。它基于动态代理(用到了cglib 和 JDK Proxy),不需要特殊的编译器来“织入”“切面”,但只支持方法拦截。

如果需要更强大和细粒度的控制(如,对构造器或属性进行拦截),则需要采用更强大的AspectJ技术。



 

 

AOP有很多专有术语非常不直观,需要细细理解。如,“通知(Advice)”、“连接点(Join point)”、“切点(Pointcut)”、“切面(Aspect)”、“引入(Introduction)”、“织入(Weaving)”等。

(《Spring实战》中就有对AOP简介(面向切面的Spring))

虽然一时半会儿理解不了,但不妨碍我们实用主义者通过示例,以写代码的方式快速上手。

 

 

2. 示例

该示例中的需求可能不是很恰当,主要是为了提供一种AOP的使用方法示例。

2.1 背景

现有一个程序 AppServer。它实现了程序包 my-api.jar 中 命名空间“my.api”下的所有接口。

如:my.api.XService、my.api.YService、my.api.ZService。

AppServer中的 XServiceImpl、YServiceImpl、ZServiceImpl 等类分别实现了这些 my.api 接口。当然这些不重要,因为我们现在介绍的AOP技术不会侵入到对这些的代码的编写。

接口示例:

 

public interface XService {
  X getX(String id);
  String addX(String name);
  void deleteX(String id);
  void updateXName(String id, String newName);
}

 

现在有一个需求:将这些接口实现类中所抛出异常的信息统一提取出来,生成 MyException 再抛出。

包装 MyException 的方法如下:

 

MyException createMyException(Throwable e) {
  return new MyException(e.getMessage());
}

 

2.2 利用Spring AOP实现需求

2.2.1 Maven依赖

目标工程基于Spring(Boot),相关配置详情此处不表。现需要引入对AspectJ的依赖。

当然,如果你已经依赖了 spring-boot-starter-aop,就不需要再引入了。因为 spring-boot-starter-aop 就是依赖于 aspectjweaver。

 

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.2</version>
</dependency>

 

2.2.2 编写AOP控制代码类

@Aspect
public class MyServiceExceptionHandler {
  @Around("execution(* my.api.*.*(..))")
  public Object invokeService(ProceedingJoinPoint jp) {
    try {
      return jp.proceed();
    } catch (Throwable e) {
      throw createMyException(e);
    }
  }

  private MyException createMyException(Throwable e) {
    return new MyException(e.getMessage());
  }
}

 

  • 用 @Aspect 注解表明这是一个切面类。我们之前引入的 AspectJ 框架会在运行时识别该注解,并利用该Handler类对那些服务类(如,XServiceImpl)进行包装。
  • @Around 注解表明我们采用的是环绕通知。因为我们需要补获Service方法抛出的异常。
    • 环绕通知(@Around)是最强大的通知类型。它会将方法封装起来。
    • 其它通知类型有:
      • @Before:方法执行前调用
      • @After:方法返回或抛出异常后调用
      • @AfterReturning:方法返回后调用
      • @AfterThrowing:方法抛出异常后调用
      • 可以自己编写样例验证它们的先后调用顺序
  • @Around括号中的内容表示我们控制的目标方法是什么样的
    • execution(* my.api.*.*(..))
    • execution 表示在方法执行时触发该控制代码
    • 第一个 * 表示匹配任意的返回类型
    • my.api 表示目标方法所述类的所在命名空间
    • 第二个 * 表示匹配任意类(包括XService、YService等目标命名空间下的所有类)
    • 第三个 * 表示匹配任意方法
    • .. 表示匹配任意参数
  • jp.proceed() 表示调用真实的方法。如,XService.getX()

 

2.2.3 最后的Bean配置

@Configuration
@EnableAspectJAutoProxy
public class Config {
  @Bean
  public MyServiceExceptionHandler myServiceExceptionHandler() {
    return new MyServiceExceptionHandler();
  }

  @Bean
  public XService xService() {
    return new XServiceImpl();
  }
  ...
}

 

@EnableAspectJAtuoProxy 注解表示启用 AspectJ 自动代理,也就是利用 @Aspect类(MyServiceExceptionHandler) 对原Service类进行包装。

 

  • 大小: 27.9 KB
  • 大小: 71.5 KB
分享到:
评论

相关推荐

    Spring Boot中使用AOP统一处理web层异常的方法

    "Spring Boot中使用AOP统一处理web层异常的方法" 本文主要介绍了在Spring Boot中使用AOP(Aspect-Oriented Programming,面向方面编程)来统一处理web层异常的方法。该方法可以使得系统在出现异常时能够正确地处理...

    Java AOP 公共异常处理,一个没有try的项目。.zip

    在实际开发中,公共异常处理是一个常见的AOP应用场景,用于统一处理可能出现的异常,提高代码的可读性和可维护性。在"Java AOP 公共异常处理,一个没有try的项目"中,我们可以探讨如何利用AOP实现优雅的异常管理,...

    Aop配置示例

    当Service层出现异常时,我们不希望这些异常直接传递到Controller并影响用户界面,而是希望通过AOP在服务层捕获异常,进行统一的处理,如记录日志、返回友好的错误信息等。 在"SpringAopMvcDemo"的Service层,我们...

    aop与spring事务处理

    - **错误处理**:统一异常处理机制。 - **日志记录**:记录关键操作的日志信息。 - **性能优化**:监控和优化程序性能。 - **事务管理**:管理业务操作中的事务边界。 #### 三、Spring事务处理 Spring 提供了...

    java基于spring注解AOP的异常处理的方法

    在Java开发中,Spring框架是广泛使用的,而Spring AOP(面向切面编程)则提供了一种优雅的方式来处理全局的异常。本篇文章将深入探讨如何使用Spring注解AOP进行异常处理,特别是基于`@ControllerAdvice`的方式。 一...

    spring基于AOP实现事务

    在Spring框架中,事务管理是核心功能之一,它允许开发者以声明式或编程式的方式处理应用中的事务。本文将深入探讨如何基于AOP(面向切面编程)来实现Spring的事务管理,特别是通过TransactionProxyFactoryBean。让...

    Spring AOP 实例

    在这个示例中,我们拦截`placeOrder`方法,验证订单的库存和数量,如果满足条件则允许执行方法,否则抛出异常。 总结,Spring AOP通过定义切面、切点、通知等概念,实现了在不修改原有代码的情况下增强程序功能,...

    Spring之AOP介绍

    ### Spring之AOP介绍 #### 一、AOP概述 面向方面编程(Aspect-Oriented Programming,简称AOP)作为一...通过上面的介绍和示例,我们可以看到Spring AOP的强大之处,以及它是如何简化开发过程中对横切关注点的处理。

    spring aop 实现权限的简单示例

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它允许我们在不修改源代码的情况下对程序的行为进行统一管理和控制。在本示例中,我们将深入探讨如何利用Spring AOP实现简单的权限验证。 首先,AOP的核心...

    Spring-AOP java2ee中的Spring框架的面向切面示例

    总的来说,Spring-AOP是Java EE开发中一个强大的工具,它通过面向切面编程的概念,帮助开发者更高效地处理系统的横切关注点,使业务逻辑更加清晰和简洁。学习和掌握Spring的AOP特性,对于提升Java EE项目的开发效率...

    springAOP实现数据字典.zip

    总的来说,"springAOP实现数据字典.zip"中的示例教程可能涵盖了以上步骤,通过AOP实现了数据字典的高效管理和使用。通过这种方式,我们可以将数据字典的逻辑封装起来,使其与业务逻辑分离,从而降低了代码的复杂性,...

    Android-框架知识整理之AndroidAOP编程思想

    - 异常处理:全局捕获异常,统一处理策略,提高用户体验。 6. **最佳实践**:使用AOP时,需要注意切面的粒度控制,避免过度使用导致代码过于复杂。同时,合理规划注解的使用,防止过度依赖导致项目难以理解和维护...

    Java实现AOP面向切面编程的实例教程共4页.pdf.z

    下面是一个简单的基于注解的AOP示例: ```java @Aspect public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { // 在方法执行前...

    Spring Aop 示例

    以下是一个简单的Spring AOP示例,展示如何使用注解定义切面和通知: ```java // 定义切面 @Aspect @Component public class LoggingAspect { // 定义切入点,匹配所有以'execute'开头的方法 @Pointcut(...

    aopalliance

    AOP通过"切面"这一概念,将这些关注点模块化,然后在运行时自动地将它们织入到程序的各个点,如方法调用前、后或异常处理。 **Spring AOP** Spring框架是Java领域广泛应用的轻量级容器,它提供了AOP支持,允许...

    pring异常处理共5页.pdf.zip

    在Spring中,异常处理主要是通过AOP(面向切面编程)来实现的,它允许我们在不修改原有业务代码的情况下,对程序运行过程中的异常进行统一管理。 【描述】:“Spring异常处理共5页.pdf.zip” 描述中的“共5页”...

    AOP面向切面编程总结

    6. **异常处理**:统一处理异常情况。 7. **工作流系统**:将业务逻辑与流程引擎分离。 #### 四、主流AOP框架 目前主流的AOP框架包括: - **AspectJ**:最强大的AOP框架之一,支持编译期、类加载期和运行期织入。...

    Spring实现AOP以及AOP的定义

    - **异常处理**:统一捕获和处理异常。 5. **Spring AOP与AspectJ的区别** - Spring AOP是基于代理的,只支持方法级别的切点,而AspectJ是编译时和加载时织入,支持更复杂的切点表达式,包括字段、构造器等。 - ...

    AOP:少数 AOP 技术示例

    **AOP示例** 假设我们有一个`UserService`类,需要在每个方法执行前后记录日志,我们可以创建一个`LoggingAspect`切面: ```java @Aspect @Component public class LoggingAspect { @Before("execution(* ...

Global site tag (gtag.js) - Google Analytics