zoukankan      html  css  js  c++  java
  • SpringBoot面向切面编程(AOP)

    Aspect

    (与SpringBoot整合)

    总结

    1. 作用位置

      try{
      	try{
      		@Around 前置环绕通知
      		@Before 前置通知
      		method.invoke(..);
             }catch(){
              @AfterThrowing 异常通知
      		throw.....;
         }finally{
      		@After 后置通知
         }
      	@AfterReturning 返回通知
      }finally{
          @Around 后置环绕通知
      }
      
    2. 执行流程

      1. 正常情况: @Around ==> @Before ==> 目标方法 ==> @After ==> @AfterReturning ==> @Around;
      2. 异常情况: @Around ==> @Before ==> 目标方法(出现异常) ==> @AfterThrowing ==> @After ==> @Around;

    代码演示

    1. 引入aop依赖

    pom.xml

            <!--    引入AOP依赖    -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    

    2. 核心业务类

    Service层

    UserService.java

    @Service
    public class UserService {
    
     public void service1(){
         System.out.println("Service-1-执行");
     }
    
     public String service2(){
         System.out.println("Service-2-执行");
         //int i = 1/0;  //异常测试
         return "Success!!!";
     }
    
     public ArrayList<String> service3(String userName){
         System.out.println("Service-3-执行");
         ArrayList<String> list = new ArrayList<>();
         list.add("Service-3-执行成功!!!");
         list.add(userName);
         return list;
     }
    
    }
    

    3. 切面

    MyAspect.java

    注:一定要将切面作为Spring组件注入容器

    @Component
    @Aspect
    public class MyAspect {
    
        //定义切入点
        @Pointcut("within(com.juyss.service.*)")
        public void pointcut(){}
    
        //环绕通知 ===> 正常情况执行在@Before和@After之前,如果执行过程中抛异常,只执行前置环绕通知,后置环绕不执行
        @Around(value = "pointcut()")
        public Object around(ProceedingJoinPoint point){
            System.out.println("前置环绕通知!!!");
            Object proceed = null;
            try {
                System.out.println("point.proceed()执行前----------------------------");
                Signature signature = point.getSignature();
                System.out.println("获取类名:"+signature.getName());
                System.out.println("point.proceed()执行前----------------------------");
                proceed = point.proceed();
                System.out.println("point.proceed()执行后----------------------------");
                System.out.println("获取返回值:"+proceed);
                System.out.println("point.proceed()执行后----------------------------");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
            System.out.println("后置环绕通知!!!");
            return proceed;
        }
    
        //前置通知 ===> 方法执行前
        @Before("pointcut()")
        public void before(){
            System.out.println("前置通知生效!!!");
        }
    
        //返回通知 ===> 方法正常执行完后执行,可以获取返回值.如果方法执行过程中抛异常,则不会执行
        @AfterReturning(value = "pointcut()",returning = "returnValue")
        public void afterReturning(Object returnValue){
            System.out.println("返回通知生效!!! ------返回值:"+returnValue);
        }
    
        //后置通知 ===> 在finally代码块中执行,无论如何都会执行的通知
        @After("pointcut()")
        public void after(JoinPoint joinPoint){
            Signature signature = joinPoint.getSignature();
            System.out.println("后置通知生效!!! ------ 方法名:"+signature.getName());
        }
    
        //异常通知 ===> 在执行过程中抛出异常时执行
        @AfterThrowing(value = "pointcut()",throwing = "e")
        public void afterThrowing(Exception e){
            System.out.println("异常通知生效!!! 异常信息:"+e.getMessage());
        }
    }
    

    4. 测试类

    AspectApplicationTests.java

    @SpringBootTest
    class AspectApplicationTests {
    
        @Autowired
        private UserService service;
    
        @Test
        public void Test(){
            service.service1();
            System.out.println("************************************************************************");
            service.service2();
            System.out.println("************************************************************************");
            service.service3("方法参数");
            System.out.println("************************************************************************");
        }
    
    }
    

    5. 测试结果

    正常运行时:

    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service1
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-1-执行
    返回通知生效!!! ------返回值:null
    后置通知生效!!! ------ 方法名:service1
    point.proceed()执行后----------------------------
    获取返回值:null
    point.proceed()执行后----------------------------
    后置环绕通知!!!
    ************************************************************************************************
    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service2
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-2-执行
    返回通知生效!!! ------返回值:Success!!!
    后置通知生效!!! ------ 方法名:service2
    point.proceed()执行后----------------------------
    获取返回值:Success!!!
    point.proceed()执行后----------------------------
    后置环绕通知!!!
    ************************************************************************************************
    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service3
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-3-执行
    返回通知生效!!! ------返回值:[Service-3-执行成功!!!, 方法参数]
    后置通知生效!!! ------ 方法名:service3
    point.proceed()执行后----------------------------
    获取返回值:[Service-3-执行成功!!!, 方法参数]
    point.proceed()执行后----------------------------
    后置环绕通知!!!
    ************************************************************************************************
    

    方法运行抛出异常时

    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service1
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-1-执行
    返回通知生效!!! ------返回值:null
    后置通知生效!!! ------ 方法名:service1
    point.proceed()执行后----------------------------
    获取返回值:null
    point.proceed()执行后----------------------------
    后置环绕通知!!!
    ************************************************************************************************
    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service2
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-2-执行
    异常通知生效!!! 异常信息:/ by zero
    后置通知生效!!! ------ 方法名:service2
    java.lang.ArithmeticException: / by zero
    	at com.juyss.service.UserService.service2(UserService.java:25)
    	##############其他异常信息省略################
    后置环绕通知!!!
    ************************************************************************************************
    前置环绕通知!!!
    point.proceed()执行前----------------------------
    获取类名:service3
    point.proceed()执行前----------------------------
    前置通知生效!!!
    Service-3-执行
    返回通知生效!!! ------返回值:[Service-3-执行成功!!!, 方法参数]
    后置通知生效!!! ------ 方法名:service3
    point.proceed()执行后----------------------------
    获取返回值:[Service-3-执行成功!!!, 方法参数]
    point.proceed()执行后----------------------------
    后置环绕通知!!!
    ************************************************************************************************
    
  • 相关阅读:
    JAVA_WEB--jsp概述
    npr_news英语新闻听力——每日更新
    词根词缀高效背单词技巧--词霸天下完整版
    python刷LeetCode:1071. 字符串的最大公因子
    python刷LeetCode:1013. 将数组分成和相等的三个部分
    python刷LeetCode:543. 二叉树的直径
    python刷LeetCode:121. 买卖股票的最佳时机
    python刷LeetCode:38. 外观数列
    python刷LeetCode:35. 搜索插入位置
    python刷LeetCode:28. 实现 strStr()
  • 原文地址:https://www.cnblogs.com/shmebluk/p/14099422.html
Copyright © 2011-2022 走看看