Spring之IOC、AOP

Spring之IOC、AOP

在学习Spring的时候,常常听见IOC、AOP,这两个东西其实就是Spring的精髓所在,特别是IOC和AOP,下面就开始讲讲IOC和AOP到底是什么

IOC(Inversion of control)

英文翻译过来就是控制反转。是一种思想即在Java中将对象的创建以及管理问题。

将控制反转进行拆分进行理解:

  • 控制:对象的创建以及管理
  • 反转:控制权交给外部环境(IOC容器)

IoC 图解

为什么要把控制权交给外部环境?

假如现在有一个对象A依赖了对象B,在普通的Java程序中,是这样写的

class A {
  private B b;
  private C c;
  // ..
  public A() {
    // 注入A依赖的对象
    this.b = new B();
    this.c = new C();
    // .. 
  }
}

class B {
  //属性...
} 

class C {
  //属性...
} 

有什么问题?如果一个对象所依赖的属性非常多,对象的构造器的代码非常的多(所依赖的对象需要我们一一去new),耦合性非常强

有没有一种方法可以简化创建对象的流程,或者干脆就不需要我们去关注创建对象的过程

那就是IOC,IOC可以让我们不用去关注对象的创建以及管理,你只需要将一个对象使用配置文件或者注解标注;Spring会自动将这个对象放入一个容器(实际上就是一个Map<key, value>)管理起来;当你在一个另一个被Spring管理起来的对象中依赖了这个对象,Spring会帮助你自动注入依赖;

示例:

@Component
@Data
class A {
  @Resource
  private B b;
  @Resource
  private C c;
}

@Component
class B {
  //属性...
} 

@Component
class C {
  //属性...
} 

可以看到代码立即简洁了;我们不再需要关注对象的创建过程以及管理,并且随着对象依赖的对象越来越多,IOC的优势会更加明显;

IOC总结

IOC是一种设计模式,它将对象的创建和管理交给了框架或容器,而不是由应用程序自己进行管理。在IOC中,对象的依赖关系由容器来维护,而不是在代码中显式硬编码。

AOP(Aspect oriented programming)

翻译为中文是 “面向切面编程”。在软件开发中,AOP 是一种编程范式,它与传统的 “面向对象编程”(OOP)相辅相成。AOP 的核心思想是将应用程序的横切关注点(cross-cutting concerns)从主业务逻辑中分离出来,以便更好地组织和管理这些横切关注点

其中的专业术语(觉得很晦涩难懂的可以先看下面的内容,再回来理解)

  • 横切关注点(cross-cutting concerns) :多个类或对象中的公共行为(如日志记录、事务管理、权限控制、接口限流等等)。
  • 切面(Aspect):对横切关注点进行封装的类,一个切面是一个类。切面可以定义多个通知,用来实现具体的功能。
  • 连接点(JoinPoint):连接点是方法调用或者方法执行时的某个特定时刻(如方法调用、异常抛出等)。
  • 通知(Advice):通知就是切面在某个连接点要执行的操作。通知有五种类型,分别是前置通知(Before)、后置通知(After)、返回通知(AfterReturning)、异常通知(AfterThrowing)和环绕通知(Around)。前四种通知都是在目标方法的前后执行,而环绕通知可以控制目标方法的执行过程。
  • 切点(Pointcut):一个切点是一个表达式,它用来匹配哪些连接点需要被切面所增强。切点可以通过注解、正则表达式、逻辑运算等方式来定义。比如 execution(* com.xyz.service..*(..))匹配 com.xyz.service 包及其子包下的类或接口。
  • 织入(Weaving):织入是将切面和目标对象连接起来的过程,也就是将通知应用到切点匹配的连接点上。常见的织入时机有两种,分别是编译期织入(AspectJ)和运行期织入(AspectJ)。
有什么好处?

假如我们需要在一些业务方法执行的前后进行例如日志记录、事务管理、权限控制、接口限流等,正常要怎么做?

不使用AOP
在这里插入图片描述

public class MyBusinessClass {
    public void doSomething() {
        // 接口限流
        System.out.println("接口限流");

        // 业务逻辑
        System.out.println("业务逻辑1正在执行...");

        // 横切关注点:记录日志
        System.out.println("记录日志:业务逻辑执行完成...");
    }
  
  public void doSomething2() {
        // 接口限流
        System.out.println("接口限流");

        // 业务逻辑
        System.out.println("业务逻辑2正在执行...");

        // 横切关注点:记录日志
        System.out.println("记录日志:业务逻辑执行完成...");
    }
  
  public void doSomething3() {
        // 接口限流
        System.out.println("接口限流");

        // 业务逻辑
        System.out.println("业务逻辑3正在执行...");

        // 横切关注点:记录日志
        System.out.println("记录日志:业务逻辑执行完成...");
    }
}

使用AOP
在这里插入图片描述

public class MyBusinessClass {
    public void doSomething() {
        // 业务逻辑
        System.out.println("业务逻辑正在执行...");
    }
  
  	public void doSomething() {
        // 业务逻辑
        System.out.println("业务逻辑正在执行...");
    }
}
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class MyAspect {

    @Before("execution(* com.example.MyBusinessClass.*())")
    public void beforeDoSomething() {
        // 横切关注点:接口限流
        System.out.println("接口限流");
    }
  
  @After("execution(* com.example.MyBusinessClass.*())")
    public void AfterDoSomething() {
        // 横切关注点:记录日志
        System.out.println("在业务逻辑执行之前执行横切关注点(after advice):记录日志");
    }
}
好处

可以看出使用AOP后

  1. 可读性提高:使用AOP后,业务代码更加简洁了,不再混杂着横切关注点的代码,提高了可读性

  2. 维护性提高:如果需要修改横切关注点(例如日志记录),在使用AOP的情况下只需修改切面代码,而不需要修改业务逻辑代码。这降低了修改的风险并提高了维护性

  3. 代码复用性增加:通俗来讲,就是不需要写那么多的重复代码了

应用场景
  • 日志记录:自定义日志记录注解,利用 AOP,一行代码即可实现日志记录。
  • 性能统计:利用 AOP 在目标方法的执行前后统计方法的执行时间,方便优化和分析。
  • 事务管理:@Transactional 注解可以让 Spring 为我们进行事务管理比如回滚异常操作,免去了重复的事务管理逻辑。@Transactional注解就是基于 AOP 实现的。
  • 权限控制:利用 AOP 在目标方法执行前判断用户是否具备所需要的权限,如果具备,就执行目标方法,否则就不执行。例如,SpringSecurity 利用@PreAuthorize 注解一行代码即可自定义权限校验。
  • 接口限流:利用 AOP 在目标方法执行前通过具体的限流算法和实现对请求进行限流处理。
  • 缓存管理:利用 AOP 在目标方法执行前后进行缓存的读取和更新。
AOP的实现方式

AOP的实现方式主要有两种:编译时(AspectJ)和运行时(Spring AOP)。以下是对两种方式的简要介绍:

  1. 编译时实现(AspectJ):
    • AspectJ语言: AspectJ是一个独立的编程语言,支持AOP编程范式。它通过特定的关键字和语法扩展Java语言,使得程序员可以直接在AspectJ语言中定义切面和通知。
    • 编译过程: 在编译时,AspectJ编译器会将AspectJ语言的代码编译成Java字节码。这个编译过程会将切面织入到目标程序中,生成一个包含横切关注点的增强类。
  2. 运行时实现(Spring AOP):
    • 动态代理: Spring AOP使用了JDK动态代理和CGLIB动态代理两种技术来实现运行时的横切关注点织入。
    • JDK动态代理: 当目标对象实现了接口时,Spring AOP会使用JDK动态代理。它通过创建实现了相同接口的代理对象,并在代理对象中添加横切关注点的逻辑。
    • CGLIB动态代理: 当目标对象没有实现接口时,Spring AOP会使用CGLIB动态代理。它通过创建目标对象的子类,并在子类中添加横切关注点的逻辑。

无论是编译时还是运行时实现,AOP的核心思想都是通过在连接点上织入切面的代码,从而实现横切关注点的功能。

参考链接:https://javaguide.cn/system-design/framework/spring/ioc-and-aop.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值