美文网首页springboot
SpringBoot 使用AOP

SpringBoot 使用AOP

作者: 月弦 | 来源:发表于2019-08-07 15:42 被阅读0次

    前言

    AOP的全称是Aspect Oriented Programming,翻译成中文是面向切面编程。它的主要思想是在程序正常执行的某一个点切进去加入特定的逻辑。AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果,对于我们开发中最常见的可能就是日志记录,事务处理,异常处理等等。以下是SpringBoot中使用AOP。

    一、pom文件

    引入aop依赖。

    <?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 http://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.1.6.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <groupId>com.huzh</groupId>
        <artifactId>springboot-aop</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <name>springboot-aop</name>
        <description>springboot-aop</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!--aop-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    二、创建切面

    这里介绍两种切面的创建方式:

    1、直接使用切面

    • @Aspect 表明是一个切面类
    • @Component 将当前类注入到Spring容器内
    • @Pointcut 切入点,其中execution用于使用切面的连接点。使用方法:execution(方法修饰符(可选) 返回类型 方法名 参数 异常模式(可选)) ,可以使用通配符匹配字符,*可以匹配任意字符。
    • @Before 在方法前执行
    • @After 在方法后执行
    • @AfterReturning 在方法执行后返回一个结果后执行
    • @AfterThrowing 在方法执行过程中抛出异常的时候执行
    • @Around 环绕通知,就是可以在执行前后都使用,这个方法参数必须为ProceedingJoinPoint,proceed()方法就是被切面的方法,上面四个方法可以使用JoinPoint,JoinPoint包含了类名,被切面的方法名,参数等信息。
    @Aspect
    @Component
    public class LogAspect {
        @Pointcut("execution(public * com.huzh.springbootaop.controller.*.*(..))")
        public void LogAspect() {
        }
    
        @Before("LogAspect()")
        public void doBefore(JoinPoint joinPoint) {
            System.out.println("doBefore");
        }
    
        @After("LogAspect()")
        public void doAfter(JoinPoint joinPoint) {
            System.out.println("doAfter");
        }
    
        @AfterReturning("LogAspect()")
        public void doAfterReturning(JoinPoint joinPoint) {
            System.out.println("doAfterReturning");
        }
    
        @AfterThrowing("LogAspect()")
        public void deAfterThrowing(JoinPoint joinPoint) {
            System.out.println("deAfterThrowing");
        }
    
        @Around("LogAspect()")
        public Object deAround(ProceedingJoinPoint joinPoint) throws Throwable {
            System.out.println("deAround");
            return joinPoint.proceed();
        }
    }
    

    2、利用自定义注解使用AOP

    • @Target
      这个注解就是表明该注解类能够作用的范围,也就是能够注解在哪,比如 类、方法、参数等。
      下面是他的一些参数:
      @Target(ElementType.TYPE) //接口、类、枚举、注解
      @Target(ElementType.FIELD) //字段、枚举的常量
      @Target(ElementType.METHOD) //方法
      @Target(ElementType.PARAMETER) //方法参数
      @Target(ElementType.CONSTRUCTOR) //构造函数
      @Target(ElementType.LOCAL_VARIABLE)//局部变量
      @Target(ElementType.ANNOTATION_TYPE)//注解
      @Target(ElementType.PACKAGE) ///包
      里面的参数是可以多选的,使用方法比如@Target({ElementType.METHOD,ElementType.TYPE})。
    • @Retention
      这个注解是保留说明,也就是表明这个注解所注解的类能在哪里保留,他有三个属性值:
      RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略
      RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略
      RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。
    • @Documented
      @Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了
      @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。
    • @Order
      @Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。如:1,2 等等。值越小拥有越高的优先级。Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。
    1. 新建自定义注解
      String param() default "":可以分为三部分
      String:代表这个注解的参数类型。
      param():这个是我们注解时需要传入的参数值的名称,如@DoneTime(param = "IndexController")。如果只有一个参数需要传入,建议使用value(),这样注解时会默认传入的,这样就可以使用@LogAnnotation(“测试”)。
      default "":需要给注解一个默认值,因为如果如果开发人员没有传入值,而且没有默认值的话,会报错。
    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public @interface DoneTime {
        String param() default "";
    }
    
    1. 创建自定义注解对应切面
      @Aspect:表明该类是一个AOP的类。
      @annotation(doneTime):需要输入实现的是哪个注解类。
      DoneTime doneTime:能获取注解时传入的数据,使用方法是doneTime.param()。
    @Aspect
    @Component
    public class DoneTimeAspect {
    
        @Around("@annotation(doneTime)")
        public Object around(ProceedingJoinPoint joinPoint, DoneTime doneTime) throws Throwable {
            System.out.println("方法开始时间是:" + new Date());
            Object o = joinPoint.proceed();
            System.out.println("方法结束时间是:" + new Date());
            return o;
        }
    }
    

    三、创建Controller类

    @RestController
    public class IndexController {
    
        @GetMapping("/index")
        @DoneTime(param = "IndexController")
        public String index() {
            System.out.println("方法执行");
            return "hello dalaoyang";
        }
    
        @GetMapping("/index2")
        public String index2() {
            System.out.println("方法2执行");
            return "hello dalaoyang";
        }
    }
    

    四、运行测试

    相关文章

      网友评论

        本文标题:SpringBoot 使用AOP

        本文链接:https://www.haomeiwen.com/subject/htdwdctx.html