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

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


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

<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,即需要被增强的类

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)

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注解配置)

<?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. 编写测试类进行测试

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. 测试结果

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

Last modification:September 6, 2018
If you think my article is useful to you, please feel free to appreciate