首页 > 其他分享 >Spring AOP 技术详解

Spring AOP 技术详解

时间:2024-04-09 17:00:48浏览次数:18  
标签:Spring 代理 详解 切面 AOP println 方法 out

学完AOP技术,真的不得不佩服发明AOP技术的人,真是个天才!!!

想要了解AOP,首先要了解什么叫代理。

1.代理

我们先来说说什么叫做代理:

        假如我要买辆奥迪A7,我不会直接去长春一汽工厂去买,为啥?路途远,而且,如果以这样方式购买,一手交钱,一手交车,事先没人给我介绍车辆配置情况,发动机型号等等,买完之后的后续维修等等都是没有人给我介绍的。当然,这些都是基于假设情况,现实肯定不能这样。那我应该去哪买奥迪A7呢?4S店。车是长春一汽生产的,卖是4S店卖的,这就是代理。4S店会买前给我介绍车辆的详细情况,卖完给我提供售后保障。这就叫方法的增强。

1.1静态代理

        静态代理,麻烦之处在于,我要创建多个代理对象,就好比,卖奥迪就开一个奥迪4S店,卖奔驰就开个奔驰4S店,那岂不是全国各地都开满了4S店?假设所有4S店服务也都是买车前介绍车辆详情,买后都是提供维修保障。这样就出现了代码冗余的情况。

1.2动态代理

        动态代理,好处就在于我只需要创建一个代理对象,我只开一家4S店,我可以销售各种车辆,我卖奥迪,就买前介绍奥迪车辆详情,买后提供奥迪售后保障。我卖奔驰,就买前介绍奔驰车辆详情,买后提供奔驰售后保障。同样能起到方法增强的作用,但是大大减少了代码的冗余。

2.AOP简介

        AOP的全称是Aspect Oriented Programming,即面向切面编程。是实现功能统一维护的一种技术,它将业务逻辑的各个部分进行隔离,使开发人员在编写业务逻辑时可以专心于核心业务,从而提高了开发效率。 作用:在不修改源码的基础上,对已有方法进行增强。

实现原理:动态代理技术。

优势:减少重复代码、提高开发效率、维护方便应用场景:事务处理、日志管理、权限控制、异常处理等方面。

3.AOP框架

        AOP是一种思想,是一种面向切面编程的思想,AOP的主要作用就是,告诉我们可以通过动态代理的方式,织入一段代码到已经写到另一段代码中去。

SpringAop 和 AspectJ 是两个框架,它主要就是通过AOP的思想,来实现面向切面编程。

因为动态代理的方式,不止一种,所以也出现了两个框架,其实实现的作用都是一样的。

但还是有区别:

springAOP是动态织入、AspectJ是静态织入 (静态织入的意思就是:运行AspectJ的代码,将需要被面向切面编程的代码生成出来,变成class文件。)

他们的核心就是: 动态代理。

Spring整合AspectJ很麻烦,有很多配置,那是因为AspectJ先出来,后来spring想,让你来和我的spring整合多麻烦呀,我自己写一个AOP的实现,所以出现了SpringAop,最开始spring其实也实现了aop,不过实现的不好,后来看AspectJ这个代码写的不错,然后就借用了AspectJ的语法,又实现了一遍,所以springaop其实是依赖AspectJ的,只不过依赖之后,配置简化了。

4.AOP术语

以上这些术语中,我们要首先理解,什么叫目标对象,这个就好比一汽工厂,目标类里面能被拦截的方法都叫连接点,什么切入点呢?就是要被增强的方法。说到拦截,就要说到切点表达式了

切点表达式(重点)

切点表达式负责拦截连接点,这个什么意思呢?程序开启,方法一个个执行,我想在某个或者某些方法上进行增强,首先我得先拦截到这些方法(也就是找到符合条件的方法),然后进行织入。

5.通知类型

通知执行顺序

目标类

package com.icss.zrgj;

import org.springframework.stereotype.Repository;

@Repository("carFactory")
public class CarFactory {
//   这是目标方法Target

    //    目标方法中的方法被称为连接点(jionpoint)
    public void sellCar() {
        System.out.println("长春一汽正在售卖一汽奥迪A7");
    }

    public int xinsuai() {
       int a=1000;
       int b=2536;
       int c=a+b;
        System.out.println("我返回一个C");
        return c;
    }

    //    以下也是一个连接点
    public void zhaoping() {
        System.out.println("长春一汽正在招聘销售人员");
        System.out.println(1/0);
    }

}

切面类

package com.icss.zrgj;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

//这是一个切面类
public class MyAspect {
/*在切面类中可定义多个方法*/

//    这个JoinPoint jionpoint 是目标方法的对象,可以用来获取目标对象的信息
    /*例如:目标方法所属于的类
    * 目标方法的名字
    * 目标方法的参数列表
    * 目标方法访问修饰符等
    * 目标方法的返回结果(不通用)
    * 目标方法的异常信息(不通用)
    * */
    public void before(JoinPoint jionpoint){
//         目标方法还未执行,后两个不适用
        System.out.println("这是前置通知");
    }
//     这两个参数分别是          ↓目标方法对象       ↓目标方法返回值
//          ↓关于切面类里面的方法返回值,我们只知道返回了,但是返回哪了不知道
    public int afterreturn(JoinPoint jionpoint,int h){
        System.out.println(h);
        System.out.println("这是后置返回通知");
        return  555;
    }
    public void after(){
        System.out.println("这是最终通知");
    }
    public void exception(JoinPoint jionpoint,Exception e){
        System.out.println(e);
    }
    /*
    * 环绕通知比较特殊它的参数类型叫ProceedingJoinPoint其实感觉意义一样*/
    public void arount(ProceedingJoinPoint jionpoint) throws Throwable {
        System.out.println("环绕前");
        jionpoint.proceed();
        System.out.println("环绕后");
    }
}

配置文件

<?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.icss.zrgj"/>
    <!--    扫描配置文件-->
    <context:property-placeholder location="jdbc.properties"/>

    <bean id="myaspect" class="com.icss.zrgj.MyAspect"/>
    <aop:config>
        <aop:pointcut id="is" expression="execution(public * com.icss.zrgj.CarFactory.* (..))"/>
        <aop:aspect ref="myaspect">
            <aop:before method="before" pointcut-ref="is"/>
            <aop:after method="after" pointcut-ref="is"/>
<!--            这个returning是绑定方法afterreturn的参数名字(它俩名字要一样),是目标方法的返回值(afterreturn方法的第二个参数是目标方法的返回值类型)-->
            <aop:after-returning method="afterreturn" returning="h" pointcut-ref="is"/>
            <aop:after-throwing method="exception" throwing="e" pointcut-ref="is"/>
            <aop:around method="arount" pointcut-ref="is"/>
        </aop:aspect>
    </aop:config>

</beans>

6.AOP代码执行过程

首先要有目标类,这个目标类可以有接口,也可以没有接口。如果有接口,底层就用JDK动态代理,如果没有接口,就用CGLIB动态代理。

接着我们要创建切面类(代理类)。

在配置文件中,首先我们要创建切面类对象,接着配置切入点和切面类。前者告诉spring,我拦截到那些方法作为切入点,后者告诉spring哪个类是切面类和哪些方法是切入点,我要织入切面类里哪个方法。

代理类中的方法如果有返回值的话,返回哪里了,这个不知道

在测试类中,再次执行目标方法,这个方法已经不是单纯的原来的方法了

注意:  目标方法的返回值  和  代理类中方法的参数的关系(可以理解为,目标对象的返回值返回到代理类方法的参数里了)

标签:Spring,代理,详解,切面,AOP,println,方法,out
From: https://blog.csdn.net/weixin_69053029/article/details/137548598

相关文章

  • 两种方式实现SpringBoot脚手架的依赖配置
    在基于SpringBoot脚手架创建项目时,通常会直接将spring-boot-starter-parent作为<parent>,如下示例:<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.10</vers......
  • 2024最新申请委托代扣开通详解,微信支付BD开通自动续费功能。
    当商家需要实现便捷的支付及资金自动管理时,微信支付的委托代扣服务将成为不可或缺的利器。比如网站会员的自动续费功能、停车厂的免密支付功能、保险费用的授权扣款功能场景需求等,开通委托代扣后,商家可以轻松实现对用户账户的自动扣款,无需手动操作,充分释放人力成本,提升效率。......
  • Spring深度学习:循环依赖及源码解析
    文章目录Spring深度学习:循环依赖及源码解析一、序言二、问题原因三、解决方案1.普通Bean对象循环依赖解决2.AOP代理场景下循环依赖解决3.AOP代理场景下多依赖解决四、源码分析:流程①:实例化对象A后,将对象A的工厂对象放入三级缓存流程②:对象A依赖对象B,在缓存中查找对象B流......
  • spring-LocalVariableTableParameterNameDiscoverer
    记录一下后期整理注:此工具类是解析class文件从class文件获取,而不是通过元空间的class对象的method获取 /***在jdk8以前java源码编译后通过反射是无法获得形参名的,在Java8及之后,编译的时候可以通过-parameters为反射生成元信息,可以获取到方法的参数名,但这......
  • Python中协程(coroutine)详解
    一、协程和线程的比较及其适用场景1共用变量问题多线程中可能出现多个线程争抢变量,所以变量需要加锁;协程中任一时刻都只有一个线程,所以变量不需要加锁。但是协程虽然不像多线程争抢变量但仍是和多线程一样共用变量的,即共用变量在某处改变在另外一处引用时也会发生改变。2协......
  • idea配置springmvc项目
    传统的web项目(含有webroot文件夹)导入IDEA需要做的一系列配置_ideawebroot-CSDN博客IDEA部署以往的springmvc项目,用外部Tomcat部署---精简版,几步操作完成_springmvc用外置的tomcat-CSDN博客参考这位博主的内容成功配置需要修改的是默认启动文件出现新的问题,js和css文件不好使,......
  • Vue2 + Spring Boot的题库管理和在线考试系统
    一个demo从0到1的搭建~使用mybatisplus快速开发springboot项目(一)--初始化-CSDN博客使用mybatisplus快速开发springboot项目(二)--业务实现_如何用mybatis-plus写业务-CSDN博客使用mybatisplus快速开发springboot项目(三)--JWT拦截器-CSDN博客使用mybatisplus快速开发springboot......
  • mybatis框架log4j日志配置详解及jar包下载
    mybatis框架配置日志步骤1.引入日志的jar包logback-classic-1.2.3.jar,logback-core-1.2.3.jar,slf4j-api-1.7.26.jar链接:百度网盘请输入提取码提取码:4ufh下载后在工程中新建一个lib文件夹如图所示:将下载好的jar包复制到lib文件夹中,并添加到库引用(不要漏掉!)如图所......
  • Springboot 添加License 以及生成证书和证书验证
    1.先准备生成cer证书及私钥,公钥##(1).生成私匙库#validity:私钥的有效期多少天 365 #alias:私钥别称 privateKey#keystore:指定私钥库文件的名称(生成在当前目录) privateKeys.keystore#storepass:指定私钥库的密码(获取keystore信息所需的密码) public_password#key......
  • Springboot计算机毕业设计海滨学院校园墙小程序【附源码】开题+论文+mysql+程序+部署
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容计算机毕业设计海滨学院校园墙小程序研究背景、意义、目的研究背景随着移动互联网技术的快速发展,微信小程序以其便捷性、即用即走的特点,迅速渗透到人们的日......