SpringAOP详解+使用aop完成添加日志

本文介绍了Spring的AOP概念,包括面向切面编程的原理和作用,阐述了为何使用AOP来处理如日志记录这样的公共行为。详细展示了如何配置AOP进行日志添加,包括导入依赖、配置SpringXML、创建接口及其实现、定义切面类等步骤。同时,讨论了AOP的通知类型和切点的系统注解及自定义注解模式的应用。
摘要由CSDN通过智能技术生成

目录

1.什么是aop

2.为什么使用aop

3. AOP体系结构

 4.使用aop完成添加日志

 (1)导入pom依赖

(2)配置spring.xml文件

(3)准备一个测试接口

(4)测试接口的实现类

(5)创建切面类 添加的日志

(6)测试

5.aop通知类型

6.切点使用系统注解模式

7.切点使用自定义注解模式


1.什么是aop

AOP(Aspect Oriented Programming)面向切面思想,是Spring的三大 核心思想之一(AOP-面向切面、IOC-控制反转、DI-依赖注入)。

AOP,一般称为面向切面,作为面向对象OOP的一种补充,用于将那 些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取并 封装为一个可重用的模块,这个模块被命名为“切面”(Aspect),减少 系统中的重复代码,降低了模块间的耦合度,提高系统的可维护性。 可用于权限认证日志事务处理

2.为什么使用aop

Java是一个面向对象(OOP)的编程语言,但它有个弊端就是当需要为多 个不具有继承关系的对象引入一个公共行为时,例如日志记录、权限 校验、事务管理、统计等功能,只能在每个对象里都引用公共行为, 这样做不便于维护,而且有大量重复代码,AOP的出现弥补了OOP的 这点不足。

3. AOP体系结构

AOP要做的三件事在哪里切入,也就是权限校验等非业务操作在哪些业务 代码中执行;什么时候切入,是业务代码执行前还是执行后;切入后做什 么事,比如做权限校验、日志记录等。

 

  • Pointcut切点,决定处理如权限校验、日志记录等在何处切入业务代 码中(即织入切面)。切点分为execution方式和annotation方式。前 者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修 饰的代码织入切面。
  • Advice:处理,包括处理时机和处理内容。处理内容就是要做什么事, 比如校验权限和记录日志。处理时机就是在什么时机执行处理内容,分 为前置处理(即业务代码执行前)、后置处理(业务代码执行后)等。 
  • Aspect切面,即Pointcut和Advice。
  • Joint point连接点,是程序执行的一个点。例如,一个方法的执行或 者一个异常的处理。在 Spring AOP 中,一个连接点总是代表一个方法 执行。 
  • Weaving:织入,就是通过动态代理,在目标对象方法中执行处理内容 的过程。

 4.使用aop完成添加日志

 (1)导入pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.2.15.RELEASE</version>
    </dependency>
    <!--切面依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>5.2.15.RELEASE</version>
    </dependency>
</dependencies>

(2)配置spring.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:comtext="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--包扫描-->
    <comtext:component-scan base-package="com.aaaa.demo02"/>
    <!--开启切面注解驱动 : 让spring可以识别切面的注解-->
    <aop:aspectj-autoproxy/>
</beans>

(3)准备一个测试接口


public interface MatheService {

    public int fun();
    //加法运算
    public void add(double a , double  b);
    //减法运算
    public void sub(double a , double  b);
    //乘法运算
    public void mul(double a , double  b);
    //除法运算
    public void div(double a , double  b);
}

(4)测试接口的实现类

@Service
public class MatheServiceImpl implements MatheService {
    //TODO 需求:执行业务代码前后添加日志
    //带返回值的方法
    public int fun(){
        System.out.println("fun方法的业务代码");
    return 100;
    }
    
    //加
    @Override
    public void add(double a, double b) {
       
        double result = a + b;
        System.out.println("计算的结果:" + result);
    }
    //减
    @Override
    public void sub(double a, double b) {
        double result = a-b ;
        System.out.println("计算的结果:"+result);
    }
    //乘
    @Override
    public void mul(double a, double b) {
        double result = a*b ;
        System.out.println("计算的结果:"+result);
    }
    //除
    @Override
    public void div(double a, double b) {
        double result = a/b ;
        System.out.println("计算的结果:"+result);
    }
}

(5)创建切面类 添加的日志

@Component //表示该类有spring容器创建
@Aspect   //表示该类为切面类
public class LogAspectj {
    /**
     *
     *  execution:表示哪些方法
     *  TODO 通配符:
     *           第一个*:表示访问任意修饰符和返回类型
     *           第二个*:表示该类下的任意类
     *           第三个*:表示任意方法
     *           .. : 表示任意参数类型和个数
     */
    //@Pointcut:切点
    @Pointcut("execution(* com.aaaa.demo02.*.*(..))")
    private void pointcut(){}
    @Before("pointcut()")//前置处理
    public void before(){
        System.out.println("前置日志~~~~~~");
    }
}

(6)测试

public class Test02 {
    public static void main(String[] args) {

        //读取spring配置文件
        ApplicationContext app = new ClassPathXmlApplicationContext("spring02.xml");
        //从spring容器获取指定的bean对象
        MatheService matheServiceImpl = (MatheService) app.getBean("matheServiceImpl");
        matheServiceImpl.div(10,10);
    }
}

5.aop通知类型

切面类中加入连接点(可以获取方法名称和参数)

 切面类中加入(后置通知 / 后置返回通知 / 异常通知)


//后置通知 :不管有没有异常都会执行
@After("pointcut()")
public void afterMethod(JoinPoint joinPoint){  //joinPoint:连接点
    Signature signature = joinPoint.getSignature(); //获取被切入的方法对象
    String name = signature.getName();  //获取方法名称
    System.out.println("后置日志~~~~~~ 方法名称:"+name);
}


//后置返回通知: 可以获取方法的返回值
@AfterReturning(value = ("pointcut()") , returning = "r")
public void afterReturningMethod(Object r){
    System.out.println("后置返回通知~~~~~返回值是:"+r);
}

//异常通知:发生异常执行
@AfterThrowing(value = ("pointcut()") , throwing = "e")
public void ex(Exception e){
    System.out.println("发生异常");
}

6.切点使用系统注解模式

配置pom/web/spring

 Controller层


@RestController  //表示该类为控制层并且该类中所有的方法返回的数据都是json数据
public class HelloController {
    @GetMapping("/hello")  //GetMapping:只处理get请求方式
    public String hello(){
        return "返回结果hello";
    }
    @PostMapping("/index")
    public String index(){
        return "返回index数据";
    }
}

日志

@Component
@Aspect
public class MyAspect {
    //定义切点
    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    private void my(){}
    //前置
    @Before("my()")
    public void aa(){
        System.out.println("前置++++++");
    }
}

7.切点使用自定义注解模式

定义自定义注解

@Target({ElementType.METHOD})   //表示该注解只能使用在方法上
@Retention(RetentionPolicy.RUNTIME)  //表示该注解在什么时候有效【Source源码时有效  CLASS字节码时有效  RUNTIME运行时有效】
@Documented
public @interface MyAnnotation {
    int value() default 0;
}

定义切点

@Component
@Aspect
public class MyAspect {
    //定义切点
    @Pointcut("@annotation(com.aaaa.demo03.MyAnnotation)")
    private void my(){}
    //前置
    @Before("my()")
    public void aa(){
        System.out.println("前置++qianqina++++");
    }
}

使用(使用自定义注解才会执行前置日志内容)

@MyAnnotation
@GetMapping("/show")
public void show(){
    System.out.println("自定义注解+++show+++");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值