再次分析-提出 Spring AOP-真正的AOP

简介: 再次分析-提出 Spring AOP-真正的AOP

😀前言

本篇的Spring-AOP系类文章第三篇因为我们前面采用原始的方式实现了一次所有本篇我们来详细Spring-AOP的的全面使用

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉


😀再次分析-提出 Spring AOP-真正的AOP

  1. 土方法 不够灵活
  2. 土方法 复用性差
  3. 土方法 还是一种硬编码(因为没有注解和反射支撑)
  4. Spring AOP 闪亮登场-底层是 ASPECTJ
  5. 有了前面的技术引导,理解 Spring AOP 就水到渠成

AOP 的基本介绍

● 什么是 AOP

AOP 的全称(aspect oriented programming) ,面向切面编程

● 示意图说明 AOP 的相关概念

一张详细图说明 AOP

😆● AOP 实现方式

  1. 基于动态代理的方式[内置 aop 实现]
  2. 使用框架 aspectj 来实现

AOP 编程快速入门

● 说明

需要引入核心的 aspect 包

在切面类中声明通知方法
  1. 前置通知:@Before
  2. 返回通知:@AfterReturning
  3. 异常通知:@AfterThrowing
  4. 后置通知:@After
  5. 环绕通知:@Around

编辑五种通知和前面写的动态代理类方法的对应关系

😮快速入门实例

● 需求说明

我们使用 aop 编程的方式,来实现手写的动态代理案例效果,就以上一个案例为例来讲解

● 代码实现步骤

导入 AOP 编程需要的jar

创建 SmartAnimalable接口
public interface SmartAnimalable {
    //求和
    float getSum(float i, float j);
    //求差
    float getSub(float i, float j);
}
创建SmartDog

注意加入注解@Component

@Component //使用@Component 当spring容器启动时,将 SmartDog注入到容器
public class SmartDog implements SmartAnimalable {
    @Override
    public float getSum(float i, float j) {
        float result = i + j;
        //result = 1 / 0; //模拟一个算术异常
        System.out.println("方法内部打印result = " + result);
        return result;
    }
    @Override
    public float getSub(float i, float j) {
        float result = i - j;
        System.out.println("方法内部打印result = " + result);
        return result;
    }
}
创建 SmartAnimalAspect类

SmartAnimalAspect 作用就是接管切面编程 , 此时原来的 MyProxyProvider 类就可以拿掉了

@Aspect //表示是一个切面类[底层切面编程的支撑(动态代理+反射+动态绑定...)]
@Component //会注入SmartAnimalAspect到容器
public class SmartAnimalAspect {
 /**
     * 
     * 1. @Before 表示前置通知:即在我们的目标对象执行方法前执行
     * 2. value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float)
     * 指定切入到哪个类的哪个方法  形式是: 访问修饰符 返回类型 全类名.方法名(形参列表)
     * 3. showBeginLog方法可以理解成就是一个切入方法, 这个方法名是可以程序员指定  比如:showBeginLog
     * 4. JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象
     * , 通过该方法,程序员可以获取到 相关信息
     *
     * @param joinPoint
     */
    @Before(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))")
    public void showBeginLog(JoinPoint joinPoint) {
        //通过连接点对象joinPoint 可以获取方法签名
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showBeginLog()[使用的myPointCut()]-方法执行前-日志-方法名-" + signature.getName() + "-参数 "
                + Arrays.asList(joinPoint.getArgs()));
    }
    // 返回通知:即把showSuccessEndLog方法切入到目标对象方法正常执行完毕后的地方
    // 1. 如果我们希望把目标方法执行的结果,返回给切入方法
    // 2. 可以再 @AfterReturning 增加属性 , 比如 returning = "res"
    // 3. 同时在切入方法增加 Object res
    // 4. 注意: returning = "res" 和 Object res 的 res名字一致
    // @AfterReturning(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))", returning = "res")
    // 使用切入点
    @AfterReturning(value = "execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float))", returning = "res")
    public void showSuccessEndLog(JoinPoint joinPoint, Object res) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showSuccessEndLog()-方法执行正常结束-日志-方法名-" + signature.getName() + " 返回的结果是=" + res);
    }
    //异常通知:即把showExceptionLog方法切入到目标对象方法执行发生异常的的catch{}
    @AfterThrowing(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))", throwing = "throwable")
    public void showExceptionLog(JoinPoint joinPoint, Throwable throwable) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showExceptionLog()-方法执行异常-日志-方法名-" + signature.getName() + " 异常信息=" + throwable);
    }
    //最终通知:即把showFinallyEndLog方法切入到目标方法执行后(不管是否发生异常,都要执行 finally{})
    @After(value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))")
    public void showFinallyEndLog(JoinPoint joinPoint) {
        Signature signature = joinPoint.getSignature();
        System.out.println("SmartAnimalAspect-切面类showFinallyEndLog()-方法最终执行完毕-日志-方法名-" + signature.getName());
    }
}

😋解读

@Before
  1. @Before 表示前置通知:即在我们的目标对象执行方法前执行
  1. value = "execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float)指定切入到哪个类的哪个方法 形式是: 访问修饰符 返回类型 全类名.方法名(形参列表)
  1. showBeginLog方法可以理解成就是一个切入方法, 这个方法名是可以程序员指定 比如:showBeginLog
  1. JoinPoint joinPoint 在底层执行时,由AspectJ切面框架, 会给该切入方法传入 joinPoint对象, 通过该方法,程序员可以获取到 相关信息
@AfterReturning

返回通知:即把showSuccessEndLog方法切入到目标对象方法正常执行完毕后的地方

  1. 如果我们希望把目标方法执行的结果,返回给切入方法
  2. 可以再 @AfterReturning 增加属性 , 比如 returning = “res”
  3. 同时在切入方法增加 Object res
  4. 注意: returning = “res” 和 Object res 的 res名字一致

@AfterReturning(value = “execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float))”, returning = “res”)

使用切入点

@AfterThrowing

异常返回:在异常通知方法中获取异常信息 可以增加属性如 throwing = “throwable”

即public void showExceptionLog(JoinPoint joinPoint, Throwable throwable

注意:throwing = “throwable” 和 showExceptionLog 的 Throwable throwable名字一致

异常通知:即把showExceptionLog方法切入到目标对象方法执行发生异常的的catch{}

@After

最终通知:即把showFinallyEndLog方法切入到目标方法执行后(不管是否发生异常,都要执行 finally{})

创建 src\beans6.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:context="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">
    <context:component-scan
            base-package="com.spring.aop.aspectj"/>
    <!-- 开启基于注解的AOP功能 -->
    <aop:aspectj-autoproxy/>
</beans>
测试
@Test
    public void testDoAround() {
        //得到spring容器
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans08.xml");
        SmartAnimalable smartAnimalable =
                ioc.getBean(SmartAnimalable.class);
        smartAnimalable.getSum(10, 2);
    }

细节说明

  1. 关于切面类方法命名可以自己规范一下,

比如 showBeginLog() . showSuccessEndLog() showExceptionLog(), showFinallyEndLog()

  1. 切入表达式的更多配置,比如使用模糊配置

@Before(value=“execution(* com.hspedu.aop.proxy.SmartDog.*(…))”)

  1. 表示所有访问权限,

所有包的下所有有类的所方法,都会被执行该前置通知方法

@Before(value=“execution(* .(…))”)

  1. 当 spring 容器开启了 < aop:aspectj-autoproxy/> ,

我们获取注入的对象, 需要以接口的类型来获取, 因为你注入的对象.getClass() 已经是代理类型了!

  1. 当 spring 容器开启了 < aop:aspectj-autoproxy/> ,

我们获取注入的对象, 也可以通过 id 来获取, 但是也要转成接口类型

7.如果每回使用注解来配置的时候都要写类的全路径麻烦可以考虑

//定义一个切入点, 在后面使用时可以直接引用, 提高了复用性

@Pointcut(value = “execution(public float com.spring.aop.aspectj.SmartDog.getSum(float, float)))”)

public void myPointCut() {}

使用如前面的

前面的@Before(value = “execution(public float com.hspedu.spring.aop.aspectj.SmartDog.getSum(float, float))”)

//这里我们使用定义好的切入点

可以写成@Before(value = “myPointCut()”)

@AfterReturning(value = “myPointCut()”, returning = “res”)

其他的类似使用

  1. 如果有多个切面类需要定义顺序可以使用

@Order(value = 2)//表示该切面类执行的顺序, value的值越小, 优先级越高

😄总结

本篇下详细的讲解了Spring-AOP的全面使用加上代码分析

😍Spring-AOP系类文章

第一篇-> Spring-AOP的基本介绍以及通过先动态代理方式实现

第二篇-> Spring-动态代理深入了解


文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
7月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
724 0
|
11月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1522 13
|
6月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
680 6
|
8月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
8月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
1070 0
|
10月前
|
负载均衡 Java API
基于 Spring Cloud 的微服务架构分析
Spring Cloud 是一个基于 Spring Boot 的微服务框架,提供全套分布式系统解决方案。它整合了 Netflix、Zookeeper 等成熟技术,通过简化配置和开发流程,支持服务发现(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、API网关(Zuul)、配置管理(Config)等功能。此外,Spring Cloud 还兼容 Nacos、Consul、Etcd 等注册中心,满足不同场景需求。其核心组件如 Feign 和 Stream,进一步增强了服务调用与消息处理能力,为开发者提供了一站式微服务开发工具包。
862 0
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
1092 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
590 24

热门文章

最新文章