Spring AOP实践

wuchangjian2021-11-15 18:43:02编程学习

面试说道AOP都会说作用是对每层记录日志。但从来都没真正实践过。

场景:编写的业务,每个函数,特别是Controller和Dao层 想把 各个函数的参数记录到日志中,方便排查之后生产上的问题。

解决:使用AOP技术。具体实践如下:

文件目录结构:

 第一步:编写注解

记得引入aspect的依赖,文章最下方贴出来了。

package com.example.demo.anno;

import java.lang.annotation.*;

/*创建日志注解*/
@Retention(RetentionPolicy.RUNTIME) //指定注解的生命周期 在运行时
@Target(ElementType.METHOD)  // 指定注解只作用在 方法(函数)上
@Documented
@Inherited //父类写了该注解 则子类默认继承的话
public @interface Logs {   //@interface 注解的格式
    String action() default ""; //注解 可以接受的参数。
}

第二步:编写切入点的逻辑

 

package com.example.demo.anno;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/*切入每个函数的的入口且有@log注解标记的函数 调用该部分:功能打印函数参数*/
@Aspect
@Component
public class AOPOfLog {

    @Around(value = "within(com.example.demo.anno..*) && @annotation(logs)")
    public Object doLogs(ProceedingJoinPoint joinPoint,Logs logs) throws Throwable {

        System.out.println("打印注解的参数:"+logs.action());

        Object[] args = joinPoint.getArgs();//函数有几个参数,agrs这个数组就会有几个元素

        System.out.println("打印切入点的函数,传入的参数是:");
        for (int i = 0; i < args.length; i++) {
            //如果是字符串或者数字则直接打印,否则打印 对象.toStirng()
            if(args[i] instanceof String || args[i] instanceof Integer) {
                System.out.print(" " + args[i]);
            }else {
                System.out.print(" "+args[i].toString());
            }
        }

        //调用切入点 的函数  即:放行拦截
        Object obj = joinPoint.proceed();
        return obj; //如果返回void 则相当于没放行

    }

}

第三步:使用注解

package com.example.demo.anno;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/")
@ResponseBody
public class TestController {

    // post请求测试 http://localhost:8080/test1?parm1=1&parm2=2
    @Logs(action = "我是test1的注解")
    @RequestMapping("/test1")
    public  Object test1(String parm1,String parm2){
        return "成功了";
    }

    //post请求测试 http://localhost:8080/test2?name=王建伟&age=18
    @Logs(action = "我是test2的注解")
    @RequestMapping("/test2")
    public  Object  test2(User user){
        return "成功了";
    }
}

class  User{
    private String name;
    private int age;

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

现象结果:在访问包下的 com.example.demo.anno 的所有标记了 @Logs的函数 都会打印传入该函数的 参数值。

前端:

后台打印:

 

 

 总结:AOP就是在执行每个函数前、后、中 都可以“插入某个代码段”,也就是面试中常说的,将每个相同业务的公共部分抽取出来 进行统一处理,不仅提高了开发效率,还提高了日后代码可维护性(实现一处修改全局修改)

 

本项目的完整pom依赖如下:

<?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.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.mybatis</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>



    <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>http://repo.e-iceblue.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>

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

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.12</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.1</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.13</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>com.itextpdf</groupId>-->
<!--            <artifactId>itext-asian</artifactId>-->
<!--            <version>5.2.0</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.7.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.9.5</version>
        </dependency>

        <dependency>
            <groupId>aopalliance</groupId>
            <artifactId>aopalliance</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.0</version>
        </dependency>

        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.1.12</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId> e-iceblue </groupId>
            <artifactId>spire.pdf</artifactId>
            <version>3.11.6</version>
        </dependency>


    </dependencies>

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


            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.2</version>

            </plugin>
        </plugins>
    </build>

</project>

 

相关文章

视频编解码器常见问题介绍

视频编解码器,是指一个能够对数字视频进行压缩或者解压缩的程序或者设备。通常...

【链表经典问题】328. 奇偶链表

一、题目描述 328.奇偶链表 给定一个单链表,把所有的奇数节点和偶数...

高仿腾讯新闻科技频道页面

HTML代码: <!DOCTYPE html> <ht...

01-JDBC

...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。