spring核心技术(下)--面向切面aop的特点加案例论证

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: spring核心技术(下)--面向切面aop的特点加案例论证

一.spring的aop的特点

      Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)的容器框架 。 上一篇已经讲解了IoC控制反转的特点,今天我们来了解面向切面AOP的世界吧!!


       1.1 aop的简介

               Spring的AOP(面向切面编程)可以理解为在编程中,我们常常会有一些通用的功能需求,比如记录日志、事务管理、权限验证等一些非业务核心代码。这些功能可能会散落在很多代码中,如果每次都手动去添加这些功能,不仅麻烦还容易出错。而AOP就是为了解决这个问题而产生的。

      1. AOP的第一个特点是它能够将这些通用功能从业务逻辑中分离出来,形成一个独立的模块,我们把这个模块称为切面(Aspect)。切面里面包含了要执行的通用功能代码。
       2. 松耦合:AOP通过在运行时动态地将切面织入到目标对象中,实现了对目标对象的横向切面扩展。这种方式不需要修改目标对象的代码,只需要在配置文件中指定切点和切面的关系,从而实现了目标对象和切面之间的松耦合。
       3. 代码复用:AOP将通用功能封装在切面中,可以在多个目标对象中复用同一个切面,避免了代码的重复编写,提高了代码的复用性。
       4. 面向切面的编程:AOP允许我们通过切面来对多个目标对象的多个方法进行统一的管理。我们可以在切面中定义通用的功能,并通过切点来指定目标对象的哪些方法需要应用这个通用功能。

       总的来说,AOP的特点包括将通用功能从业务逻辑中分离出来、松耦合、代码复用和面向切面的编程。这些特点使得AOP成为了一个重要的编程范式,可以提高代码的可维护性、可扩展性和开发效率。

       1.2 举例

               比如:当我们大家伙合伙做一个线上书城的项目,如果其中有个贪心的人使用系统,上架了一本明令禁止售卖的书,然后被人举报了,但是这个时候贪心的人下架了该书,而那个人又没有截图,证据,那是不是就发现不了,再者如果客户已经在该系统中下单,但是,客户付了钱之后,那个贪心的人想白嫖将该订单删除,那是不是就没有记录,客户也找不到投诉,那么这个时候,我们就要在系统添加日志文件,记录每一次的交易,上架,下架的数据,那么是不是就可以被记录,而spring的aop就是这样的来完成这些,除必要的增删改之外的技术代码,非业务的核心代码

二.spring的aop的专业术语

       之前我们的项目代码但是从上往下依次执行,而现在加入了面向切面的思想,所以当我们的代码执行到目标对象是,查看连接点是否有前置通知,先执行前置通知,再执行目标方法,如果没有前置通知,那么就直接执行目标方法,最后看连接点上是否有后置通知,如果有,就再执行后置通知,如果没有就执行完了

  1. 连接点(Joinpoint):程序执行过程中明确的点,如方法的调用,或者异常的抛出.
  2. 目标(Target):被通知(被代理)的对象,就是完成具体的业务逻辑 ,比如书籍的增删改查
  3. 通知(Advice):在某个特定的连接点上执行的动作,同时Advice也是程序代码的具体实现,例如一个实现日志记录的代码(通知有些书上也称为处理)  ,完成切面编程,非业务核心代码
  4. 代理(Proxy):将通知应用到目标对象后创建的对象(代理=目标+通知),  例子:外科医生+护士只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的
  5. 切入点(Pointcut):多个连接点的集合,定义了通知应该应用到那些连接点 , (也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序),比如给新增方法添加日志功能
  6.  适配器(Advisor):适配器=通知(Advice)+切入点(Pointcut)

        注:目标对象只负责业务逻辑代码

       通知对象负责AOP代码,这二个对象都没有AOP的功能,只有代理对象才有

三.论证模拟

       3.1.前置通知

      首先,我们先写service接口和实现类进行模拟,在里面写两个方法

package com.zking.aop.service;
/**
 * @author yinzi
 * @create 2023-08-17 14:52
 */
public interface IBookService {
    // 购书
    public boolean buy(String userName, String bookName, Double price);
    // 发表书评
    public void comment(String userName, String comments);
}

       然后,写实现类,重新这两个方法,并且做了一个价格的判断

package com.zking.aop.service;
import com.zking.exception.PriceException;
/**
 * @author yinzi
 * @create 2023-08-17 14:54
 */
public class BookServiceImpl implements IBookService{
    public BookServiceImpl() {
        super();
    }
    public boolean buy(String userName, String bookName, Double price) {
        // 通过控制台的输出方式模拟购书
        if (null == price || price <= 0) {
            throw new PriceException("book price exception");
        }
        System.out.println(userName + " 买了 " + bookName + ", 花了 " + price);
        return true;
    }
    public void comment(String userName, String comments) {
        // 通过控制台的输出方式模拟发表书评
        System.out.println(userName + "评论:" + comments);
    }
}

      接下来要写上面价格判断的异常

package com.zking.exception;
public class PriceException extends RuntimeException {
  public PriceException() {
    super();
  }
  public PriceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
    super(message, cause, enableSuppression, writableStackTrace);
  }
  public PriceException(String message, Throwable cause) {
    super(message, cause);
  }
  public PriceException(String message) {
    super(message);
  }
  public PriceException(Throwable cause) {
    super(cause);
  }
}

      然后,我们先创建一个类,将类名.方法名,携带的参数,作为日志存储到数据库。

package com.zking.aop.advice;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.aop.MethodBeforeAdvice;
/**
 * 调用项目中的某一接口实现类的方式时,将类名.方法名,携带的参数,作为日志存储到数据库。
 * @author yinzi
 *
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
    public void before(Method method, Object[] args, Object target) throws Throwable {
        String targetName = target.getClass().getName();//方法类
        String methodName = method.getName();//方法的名字
        String params = Arrays.toString(args);//方法参数
        String msg = "【系统日志】:前置日志->"+targetName+"."+methodName+",携带的参数:"+params;
        System.out.println(msg);
    }
}

       最后,我们进行一个配置

前台论证:

       3.2.后置通知

      有了前面的铺垫,现在我们直接再创建一个后置通知的类,比起前置通知,多了一个参数,就是返回参数

package com.zking.aop.advice;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
 * @author yinzi
 * @create 2023-08-17 15:51
 */
public class MyAfterReturningAdvice implements AfterReturningAdvice {
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        String targetName = target.getClass().getName();
        String methodName = method.getName();
        String params = Arrays.toString(args);
        String msg = "【系统日志】:后置日志->" + targetName + "." + methodName + ",携带的参数:" + params + ";目标对象所调用的方法的返回值:"
                + returnValue;
        System.out.println(msg);
    }
}

      其次,配置文件即可

最后,前台看结果:

       3.3.环绕通知

       就是结合了前置通知和后置通知,它两个都有所以一般常用这个,

      它只有一个参数,但是这一个参数相当于上面前置通知和后置通知的3,4个参数

package com.zking.aop.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
 * 环绕通知
 * @author Administrator
 *
 */
public class MyMethodInterceptor implements MethodInterceptor {
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object target = invocation.getThis();
        Method method = invocation.getMethod();
        Object[] args = invocation.getArguments();
        String targetName = target.getClass().getName();
        String methodName = method.getName();
        String params = Arrays.toString(args);
        String msg = "【环绕通知】:正在调用->" + targetName + "." + methodName + ",携带的参数:" + params;
        System.out.println(msg);
        Object returnValue = invocation.proceed();
        String msg2 = "【环绕通知】:目标对象所调用的方法的返回值:" + returnValue;
        System.out.println(msg2);
        return returnValue;
    }
}

           然后就是配置文件

最后前台测试:

   3.4.异常通知

       老样子,先建一个类,但是注意,这个异常通知的类,重写的话,方法名字只能是这个,否则报错

然后就是配置文件

最后前台测试;

因为前面那个异常的类,及service类做了价格的判断

       3.5.过滤通知

       过滤通知就是那个适配器,它不需要再建一个类,直接再配置文件里面配置就可以了,需要正则判断,这里举例过滤的是后置通知

前台结果:

今天就分享到这啦!!

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
1月前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
26天前
|
监控 安全 Java
什么是AOP?如何与Spring Boot一起使用?
什么是AOP?如何与Spring Boot一起使用?
53 5
|
1月前
|
Java 开发者 Spring
深入解析:Spring AOP的底层实现机制
在现代软件开发中,Spring框架的AOP(面向切面编程)功能因其能够有效分离横切关注点(如日志记录、事务管理等)而备受青睐。本文将深入探讨Spring AOP的底层原理,揭示其如何通过动态代理技术实现方法的增强。
63 8
|
1月前
|
Java 开发者 Spring
Spring AOP 底层原理技术分享
Spring AOP(面向切面编程)是Spring框架中一个强大的功能,它允许开发者在不修改业务逻辑代码的情况下,增加额外的功能,如日志记录、事务管理等。本文将深入探讨Spring AOP的底层原理,包括其核心概念、实现方式以及如何与Spring框架协同工作。
|
1月前
|
XML 监控 安全
深入调查研究Spring AOP
【11月更文挑战第15天】
44 5
|
1月前
|
Java 开发者 Spring
Spring AOP深度解析:探秘动态代理与增强逻辑
Spring框架中的AOP(Aspect-Oriented Programming,面向切面编程)功能为开发者提供了一种强大的工具,用以将横切关注点(如日志、事务管理等)与业务逻辑分离。本文将深入探讨Spring AOP的底层原理,包括动态代理机制和增强逻辑的实现。
44 4
|
1月前
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
149 1
什么是AOP面向切面编程?怎么简单理解?
|
1月前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
39 1
|
1月前
|
XML Java 开发者
论面向方面的编程技术及其应用(AOP)
【11月更文挑战第2天】随着软件系统的规模和复杂度不断增加,传统的面向过程编程和面向对象编程(OOP)在应对横切关注点(如日志记录、事务管理、安全性检查等)时显得力不从心。面向方面的编程(Aspect-Oriented Programming,简称AOP)作为一种新的编程范式,通过将横切关注点与业务逻辑分离,提高了代码的可维护性、可重用性和可读性。本文首先概述了AOP的基本概念和技术原理,然后结合一个实际项目,详细阐述了在项目实践中使用AOP技术开发的具体步骤,最后分析了使用AOP的原因、开发过程中存在的问题及所使用的技术带来的实际应用效果。
70 5
|
1月前
|
Java Maven Spring
Spring 小案例体验创建对象的快感
本文介绍了如何在IDEA中创建一个Spring项目,包括项目创建、配置pom.xml文件以引入必要的依赖、编写实体类HelloSpring及其配置文件applicationContext.xml,最后通过测试类TestHelloSpring展示如何使用Spring的bean创建对象并调用方法。
35 0