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日志并进行多维度分析。
相关文章
|
13天前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
4天前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
30 9
|
12天前
|
存储 缓存 Java
在Spring Boot中使用缓存的技术解析
通过利用Spring Boot中的缓存支持,开发者可以轻松地实现高效和可扩展的缓存策略,进而提升应用的性能和用户体验。Spring Boot的声明式缓存抽象和对多种缓存技术的支持,使得集成和使用缓存变得前所未有的简单。无论是在开发新应用还是优化现有应用,合理地使用缓存都是提高性能的有效手段。
15 1
|
26天前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理
|
1月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
56 7
|
2月前
|
缓存 Java 开发者
Spring高手之路22——AOP切面类的封装与解析
本篇文章深入解析了Spring AOP的工作机制,包括Advisor和TargetSource的构建与作用。通过详尽的源码分析和实际案例,帮助开发者全面理解AOP的核心技术,提升在实际项目中的应用能力。
26 0
Spring高手之路22——AOP切面类的封装与解析
|
1月前
|
JavaScript 前端开发 Java
【颠覆传统】Spring框架如何用WebSocket技术重塑实时通信格局?揭秘背后的故事与技术细节!
【9月更文挑战第4天】随着Web应用对实时交互需求的增长,传统的HTTP模型已无法满足现代应用的要求,特别是在需要持续、双向通信的场景下。WebSocket协议由此诞生,提供全双工通信渠道,使服务器与客户端能实时互发消息。作为Java开发中最受欢迎的框架之一,Spring通过其WebSocket模块支持这一协议,简化了WebSocket在Spring应用中的集成。
41 0
|
2月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
42 0
|
2月前
|
前端开发 Java Spring
Spring与Angular/React/Vue:当后端大佬遇上前端三杰,会擦出怎样的火花?一场技术的盛宴,你准备好了吗?
【8月更文挑战第31天】Spring框架与Angular、React、Vue等前端框架的集成是现代Web应用开发的核心。通过RESTful API、WebSocket及GraphQL等方式,Spring能与前端框架高效互动,提供快速且功能丰富的应用。RESTful API简单有效,适用于基本数据交互;WebSocket支持实时通信,适合聊天应用和数据监控;GraphQL则提供更精确的数据查询能力。开发者可根据需求选择合适的集成方式,提升用户体验和应用功能。
74 0
|
2月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
72 0