Fork me on GitHub

Spring 整合 AspectJ 的 AOP 处理异常

注:本文只介绍如何处理异常通知

工作需要,之前的项目上线后,基本是靠运维查看并发现运行中的异常。新的项目启动一段时间了,单纯的靠运维人工发现程序运行中的异常效率低下,可以利用 Spring 的 AOP(Aspect Oriented Programming面向切面编程)来实现自动捕获项目中发生的异常。


1. 创建一个 Maven 项目,配置 pom 文件,引入相关依赖 jar 包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.2.4.RELEASE</version>
<scope>provided</scope>
</dependency>
</dependencies>

2. 创建目标 target,即需要被增强的类

1
2
3
4
5
6
7
8
9
10
11
12
import net.okdi.core.service.PromoService;
import org.springframework.stereotype.Service;

@Service
public class PromoServiceImpl implements PromoService {
public String insertRecord(String memberId) {
System.out.println("开始添加记录。。。");
int i = 1 / 0; // 除0异常
System.out.println("添加记录完毕。。。");
return null;
}
}

3. 创建通知(即增强类 advice)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package net.okdi.core.exception;

import org.aspectj.lang.JoinPoint;

/**
* 异常通知增强
*/
public class ExceptionHelper {

public void afterThrow(JoinPoint jp, Throwable ex) {
System.out.println("************************");
// 程序运行抛出异常后的业务处理...
System.out.println("正常业务处理");
System.out.println(ex.getMessage());
System.out.println("************************");
}
}

在 aspectj 框架中它的增强可以不实现任何接口,只需要定义出增强功能(方法)。两个参数 JoinPoint 和 Exception。JoinPoint 是切点,它的 getArgs() 方法可以获取传入的参数;getSignature() 方法返回一个 Signature 对象,这个对象的 getDeclaringTypeName() 方法可以获取异常发生的类的全路径,getName() 方法可以获取抛出异常的方法。


4. 在 Spring 的 xml 配置文件中配置(或者使用 @AfterThrowing 注解配置)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

<!-- 注解扫描包 -->
<context:component-scan base-package="net.okdi"/>

<!-- 配置目标 -->
<bean id="promoService" class="net.okdi.core.service.impl.PromoServiceImpl"/>

<!-- 配置通知 -->
<bean id="exceptionAdvice" class="net.okdi.core.exception.ExceptionHelper"/>

<!-- aop:config声明,aop:aspect配置切面 proxy-target-class默认false(有接口jdk动态代理,无接口cglib动态代理)true强制cglib代理 -->
<aop:config proxy-target-class="true">
<aop:aspect ref="exceptionAdvice">
<aop:after-throwing method="afterThrow" pointcut="execution(* net.okdi.core..*(..))" throwing="ex"/>
</aop:aspect>
</aop:config>

</beans>

proxy-target-class 默认false(有接口 jdk 动态代理,无接口 cglib 动态代理)修改为 true 强制使用 cglib 动态代理。


5. 编写测试类进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import net.okdi.core.service.PromoService;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
public class Test {

@Autowired
private PromoService promoService;

@org.junit.Test
public void test() {
promoService.insertRecord("");
}
}

6. 测试结果

image
至此,利用 Spring 整合 AspectJ 框架进行 AOP 中的异常通知处理开发完毕!

------本文结束------
0%