Spring AspectJ编程--各种通知执行的顺序

public interface UserService {
    String add();
    void delete();
}
@Service("userService")
public class UserServiceImpl implements UserService {

    @Override
    public String add() {
        System.out.println("执行add()方法。。。");
        return "李四";
    }

    @Override
    public void delete() {
        System.out.println("执行delete()方法。。。");
    }

}
public interface StudentService {
    String findById();
    String findAll();
}
@Service("studentService")
public class StudentServiceImpl implements StudentService {

    @Override
    public String findById() {
        System.out.println("执行findById()方法。。。");
        // 为了测试异常通知
        System.out.println(1/0);
        return "stu张三1";
    }

    @Override
    public String findAll() {
        System.out.println("执行findAll()方法。。。");
        return "stu张三2";
    }

}

  切面类 MyAdvices

package com.oy.entity;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * 切面类:通知的集合
 * @author oy
 * @version 1.0
 * @date 2018年12月30日
 * @time 下午7:25:27
 */
@Component
@Aspect
public class MyAdvices {
    // 声明公共切入点
    @Pointcut("execution(* com.oy.entity.*Impl.*(..))")
    private void myPointCut() {
    }
    
    @Before(value="execution(* com.oy.entity.*Impl.*(..))")
    public void myBefore(JoinPoint joinPoint){
        //获取目标方法名:joinPoint.getSignature().getName()
        System.out.println("前置通知 ,目标方法名为:" + joinPoint.getSignature().getName());
    }
    
    @AfterReturning(value="myPointCut()", returning="ret")
    // 将切入点的返回值ret传递给通知
    public void myAfterReturning(JoinPoint joinPoint, Object ret){
        System.out.println("后置通知 ,目标方法名为: " + joinPoint.getSignature().getName() + " , 返回值为-->" + ret);
    }
    
    @Around(value="myPointCut()")
    public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{
        System.out.println("环绕通知,前增强代码。。。");
        
        //手动执行目标方法
        Object obj = joinPoint.proceed();
        
        System.out.println("环绕通知,后增强代码。。。");
        return obj;
    }
    
    @AfterThrowing(value="myPointCut()", throwing="e")
    // 将切入点的异常对象e传递给通知
    public void myAfterThrowing(JoinPoint joinPoint, Throwable e){
        System.out.println("=============执行抛出异常后的增强代码 start=============");
        System.out.println("抛出异常通知 ,异常信息: " + e.getMessage());
        System.out.println("=============执行抛出异常后的增强代码 end=============");
    }
    
    @After(value="myPointCut()")
    public void myAfter(JoinPoint joinPoint){
        System.out.println("最终通知:我是finally里面的代码。。。即使发生异常我也要执行。。。");
    }
}

  beans.xml

<?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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    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">

    <!-- 组件扫描 -->
    <context:component-scan base-package="com.oy.entity"/>
    
    <!-- 声明aop注解生效 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
</beans>

  测试类

package com.oy.test;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.oy.entity.StudentService;
import com.oy.entity.UserService;

/**
 * Spring AspectJ编程
 * 
 * @author oy
 * @version 1.0
 * @date 2018年12月30日
 * @time 上午10:01:18
 */
public class UserServiceProxyTest {
    ClassPathXmlApplicationContext ctx = null;
    
    @Before
    public void before() {
        ctx = new ClassPathXmlApplicationContext("beans.xml");
    }
    
    @After
    public void after() {
        ctx.close();
    }
    
    /*
     * 测试结果:
        环绕通知,前增强代码。。。
        前置通知 ,目标方法名为:add
        执行add()方法。。。
        环绕通知,后增强代码。。。
        最终通知:我是finally里面的代码。。。即使发生异常我也要执行。。。
        后置通知 ,目标方法名为: add , 返回值为-->李四
        ================================
        环绕通知,前增强代码。。。
        前置通知 ,目标方法名为:delete
        执行delete()方法。。。
        环绕通知,后增强代码。。。
        最终通知:我是finally里面的代码。。。即使发生异常我也要执行。。。
        后置通知 ,目标方法名为: delete , 返回值为-->null
     */
    @Test
    public void test1() {
        // getBean("目标类userServiceImpl的id"),从spring容器获得目标类,如果配置了aop,spring将自动生成代理
        UserService userService = (UserService)ctx.getBean("userService");
        userService.add();
        System.out.println("================================");
        userService.delete();
    }
    
    /*
     * 测试结果:
          环绕通知,前增强代码。。。
          前置通知 ,目标方法名为:findById
          执行findById()方法。。。
          最终通知:我是finally里面的代码。。。即使发生异常我也要执行。。。
          =============执行抛出异常后的增强代码 start=============
          抛出异常通知 ,异常信息: / by zero
          =============执行抛出异常后的增强代码 end=============
     */
    
    @Test
    public void test2() {
        StudentService stuentService = (StudentService)ctx.getBean("studentService");
        stuentService.findById();// 测试异常通知时,这句代码抛出异常,后面代码无法执行。
        
        System.out.println("================================");
        stuentService.findAll();
        
    }

}

---

原文地址:https://www.cnblogs.com/xy-ouyang/p/13757661.html