所有分类
  • 所有分类
  • 未分类

Spring之AOP系列-使用/实例

简介

本文介绍Spring(SpringBoot)的AOP的用法,以及其顺序的控制。

AOP的执行流程图

正常执行时的流程

代码抛异常时的流程

创建工程

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>demo_springaop-simple</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo_springaop-simple</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <!--            <exclusions>-->
            <!--                <exclusion>-->
            <!--                    <groupId>org.junit.vintage</groupId>-->
            <!--                    <artifactId>junit-vintage-engine</artifactId>-->
            <!--                </exclusion>-->
            <!--            </exclusions>-->
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.20</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

公共代码

启动类

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoSpringaopSimpleApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoSpringaopSimpleApplication.class, args);
    }
}

Entity

package com.example.demo.entity;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String userName;
    private String note;
}

Service

package com.example.demo.service;

import com.example.demo.entity.User;

public interface UserService {
    public void printUser(User user);
}
package com.example.demo.service.impl;

import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {
    @Override
    public void printUser(User user) {
        if (user == null) {
            throw new RuntimeException("检查用户参数是否为空");
        }
        System.out.print("id = " + user.getId());
        System.out.print("\t userName = " + user.getUserName());
        System.out.println("\t note = " + user.getNote());
    }
}

Controller

package com.example.demo.controller;

import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/user")
@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping("/print")
    @ResponseBody
    public User testPrint(User user) {
        userService.printUser(user);
        return user;
    }

    @RequestMapping("/add")
    @ResponseBody
    @OperationLog(type = "添加", desc = "添加数据")
    public User testAdd(User user) {
        return user;
    }

    @RequestMapping("/update")
    @ResponseBody
    @OperationLog(type = "更新", desc = "更新数据")
    public User testUpdate(User user) {
        userService.printUser(user);
        return user;
    }
}

AOP代码

代码

package com.example.demo.aspect;

import com.example.demo.annotation.OperationLog;
import com.example.demo.common.util.JsonUtil;
import com.example.demo.entity.User;
import com.sun.org.apache.regexp.internal.RE;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
// @Order(1)
public class SimpleAspect {
    @Pointcut("execution(* com.example.demo.service.impl.UserServiceImpl.printUser(..))")
    // 多个切点时可指定优先级
    // @Order(1)
    public void pointcut() {

    }

    @Before("pointcut()")
    public void before() {
        System.out.println("############################ SimpleAspect.before ############################");
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("############################ SimpleAspect.around ############################");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("joinPoint.getTarget().toString()  : " + joinPoint.getTarget().toString());
        System.out.println("methodSignature.getName()         : " + methodSignature.getName());
        System.out.println("method.getName()                  : " + method.getName());
        System.out.println("method.getReturnType().getName()  : " + method.getReturnType().getName());

        Object[] objects = joinPoint.getArgs();
        System.out.println(JsonUtil.toJson(objects));

        System.out.println("------------ SimpleAspect.around: proceed之前 ------------");
        Object object = joinPoint.proceed();
        System.out.println("------------ SimpleAspect.around: proceed返回值 ------------");
        System.out.println(JsonUtil.toJson(object));
        System.out.println("------------ SimpleAspect.around: proceed之后 ------------");

        return object;
    }

    @AfterReturning(value = "pointcut()", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, Object returnValue) {
        System.out.println("############################ SimpleAspect.afterReturning ############################");
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        System.out.println("------------ SimpleAspect.afterReturning: 方法名字 ------------");
        System.out.println(method.getName());
        System.out.println("------------ SimpleAspect.afterReturning: 返回值 ------------");
        System.out.println(JsonUtil.toJson(returnValue));
    }

    @AfterThrowing(value = "pointcut()", throwing = "throwingValue")
    public void afterThrowing(JoinPoint joinPoint, Throwable throwingValue) {
        System.out.println("############################ SimpleAspect.afterThrowing ############################");
        // MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        // Method method = methodSignature.getMethod();
        System.out.println("------------ SimpleAspect.afterThrowing: 异常信息 ------------");
        System.out.println(throwingValue.getMessage());
    }

    /**
     * 无法获得返回值,只能获得参数
     */
    @After("pointcut()")
    public void after() {
        System.out.println("############################ SimpleAspect.after ############################");
    }
}

测试

后端结果

############################ SimpleAspect.around ############################
joinPoint.getTarget().toString()  : com.example.demo.service.impl.UserServiceImpl@36c999c9
methodSignature.getName()         : printUser
method.getName()                  : printUser
method.getReturnType().getName()  : void
[{"id":321,"userName":"Tony","note":"abc"}]
------------ SimpleAspect.around: proceed之前 ------------
############################ SimpleAspect.before ############################
id = 321	 userName = Tony	 note = abc
############################ SimpleAspect.afterReturning ############################
------------ SimpleAspect.afterReturning: 方法名字 ------------
printUser
------------ SimpleAspect.afterReturning: 返回值 ------------
null
############################ SimpleAspect.after ############################
------------ SimpleAspect.around: proceed返回值 ------------
null
------------ SimpleAspect.around: proceed之后 ------------

可以看到,返回值为null,因为printUser方法没有返回值。 

0

评论2

请先

  1. 代码示例展示不全bug
    空指针 2024-02-23 0
    • 代码太长会折叠,点一下下边的展开按钮即可。
      自学精灵 2024-02-23 0
显示验证码
没有账号?注册  忘记密码?

社交账号快速登录