Spring特性之一——AOP面向切面编程

简介: Spring特性之一——AOP面向切面编程

带着问题去阅读

  • 什么是面向切面编程?(是什么+为什么)
  • 如何使用AOP?(怎么用)

什么是AOP?

AOP,全称:Aspect Oriented Programming,即面向切面编程。它最早是在1997年的面向对象编程大会上提出来的概念,并于2001年在AspectJ中得到首次实践。


与面向对象OOP不同的是,AOP并不是将程序抽象成各个层次的对象,而是将程序抽象成一个一个的切面。

何为切面?

简单的理解,就是将程序在一些特定的地点(比如在某个函数调用之前、返回之后等)切分开来,并在这些特定的地点插入一些程序片段,从而实现代码复用、逻辑判断等。

那,为什么要这么做?

先看下面这幅图:

3f723a8482233f15f608ddca28c91fe4.png

三个Service服务都需要进行安全检查、事务执行、其他处理,这三个必备而通用的步骤。

在传统的面向过程的编程中,直接复制相同代码肯定是不可取的,稍微高明的做法是将**这段相同的代码提取为一个方法,**而后在需要使用的地方去调用这个方法。但当之后新增一个需求或删减需求时,都得去调用的地方进行更改,会造成一定的时间开销。

其实我们可以这样看:三个Service在执行到一定的过程时,被拦腰斩断,强行插入了安全、事务、其他这三个执行环节,而不会影响这些程序之后的运行。

这就是对AOP的简单理解,要想进一步理解就得靠之后的例子以及经常的使用。

AOP经常被用来进行安全检查、打印日志、运行监控等功能。

在介绍如何使用AOP之前,需要提前了解一下AOP的有关术语。

AOP术语

AOP的术语是围绕“切面”这个核心概念所设计的。

  • 连接点(JoinPoint)

连接点是指程序执行过程中的特定位置,比如方法调用前、后、抛出异常等。

连接点=执行主体+具体位置。

举个例子,Student这个类中有一个方法getName()。

那么Student.getName()就是一个执行主体,它存在多个具体位置:before、after、around、return等。

意思就是在getName()方法执行前、后、前后、返回后再执行想要插入的代码逻辑(就是强行加进去的代码)

这些连接点有什么用?

它表明了在程序的那些地方可以植入(术语叫做——织入)代码,即——见缝插针!

  • 通知(Advice)

通知这个概念需要和连接点相结合来理解:通知就是告诉将要执行的植入代码,某个连接点已经触发了,你要执行就赶紧!

通过通知(也成增强点或者横切关注点),可以使得在特定的连接点执行特定的代码。

Spring现在有五类通知:

51e42698f696d3b359da407e2e4b0f5e.png

  • 切入点(PointCut)

切入点的概念其实是一个过滤的条件,是用来找到连接点的执行主体——一个切入点对应多个连接点(因为连接点存在之前、之后等情况)。

  • 通知器(Advisor)

通知器=切入点+通知。

简单理解为一个触发器+执行器。

  • 切面(Aspect)

切面=切入点+通知。

跟通知器的区别就在于,切面无需实现通知接口(看代码),但配置文件中需要写明;但通知器需要实现通知接口。

  • 织入(Weaving)

将一部分代码强行插入到执行程序中,就是所谓的织入。

PS:术语的英译之后较难理解,还是结合代码领会其意思即可。

如何使用AOP?

这里借用SharpCJ所写博客中的例子来帮助理解AOP中的术语以及具体的使用方式:

现在有一个IBuy接口:

package com.sharpcj.aopdemo.test1;

public interface IBuy {
    String buy();
}

Boy和Girl实现了这个接口:

package com.sharpcj.aopdemo.test1;

import org.springframework.stereotype.Component;

@Component
public class Boy implements IBuy {
    @Override
    public String buy() {
        System.out.println("男孩买了一个游戏机");
        return "游戏机";
    }
}

package com.sharpcj.aopdemo.test1;

import org.springframework.stereotype.Component;

@Component
public class Girl implements IBuy {
    @Override
    public String buy() {
        System.out.println("女孩买了一件漂亮的衣服");
        return "衣服";
    }
}

编写了一个测试类:

package com.sharpcj.aopdemo;

import com.sharpcj.aopdemo.test1.Boy;
import com.sharpcj.aopdemo.test1.Girl;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class AppTest {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new 
          AnnotationConfigApplicationContext(AppConfig.class);
        Boy boy = context.getBean("boy",Boy.class);
        Girl girl = (Girl) context.getBean("girl");
        boy.buy();
        girl.buy();
    }
}

结果为:

da786d67e1a2c60165cc2399f34a2333.png

那么,如何使用切面?

先定义一个切面类,BuyAspectJ.java

package com.sharpcj.aopdemo.test1;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class BuyAspectJ {
    @Before("execution(* com.sharpcj.aopdemo.test1.IBuy.buy(..))")
    public void haha(){
        System.out.println("男孩女孩都买自己喜欢的东西");
    }
}

这里的注解@AspectJ就表示这个类是一个切面(切面就是一个切入点+通知),与此同时(“execution(* com.sharpcj.aopdemo.test1.IBuy.buy(…))”)声明了切点是执行buy()方法,@Before表示在这个方法执行之前。

2f4b145b5913e1e04576c94652f35657.png


再次运行一下,结果为:

3bf4292f65497eafb57ab912558b65aa.png

可以看到,与之前的结果相比,程序执行过程中插入了切面类中的方法!

关于AOP进一步的学习()(比如AOP注解、XML配置等等)可以直接去看AOP的官方文档,或者参考资料。

与OOP的关系

需要注意的是AOP与OOP并不存在谁高谁低,非此即彼,AOP可以认为是对OOP的补充(要知道,AOP是在OOP大会上提出来的!)。

OOP封装的是方法和属性,是逻辑对象层面的概念;

而AOP封装的是一些通用的业务,面向的是某个步骤或者环节,从而实现各个环节之间的松耦合

唯有两者的结合才可以使得彼此更为强大,一如它们所构建的框架——Spring。

参考资料

AOP专业术语

面向切面编程

相关文章
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
374 0
|
3月前
|
Java API 开发者
Spring 控制反转与依赖注入:从玄学编程到科学管理
在传统开发中,手动`new`对象导致紧耦合、难以维护和测试。控制反转(IoC)将对象创建交给框架,实现解耦。Spring通过IOC容器自动管理对象生命周期,开发者只需声明依赖,无需关心创建细节。依赖注入(DI)是IoC的具体实现方式,支持构造器、Setter和字段注入。构造器注入推荐使用,保证依赖不可变且易于测试。对于多个同类型Bean,可用`@Qualifier`或`@Primary`解决冲突。此外,Spring还支持依赖查找(DL),开发者主动从容器获取Bean,适用于动态场景,但侵入性强。掌握IoC与DI,有助于构建灵活、可维护的Spring应用。
|
28天前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
3月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
30天前
|
监控 Java Spring
AOP 切面编程
AOP(面向切面编程)通过动态代理在不修改源码的前提下,对方法进行增强。核心概念包括连接点、通知、切入点、切面和目标对象。常用于日志记录、权限校验、性能监控等场景,结合Spring AOP与@Aspect、@Pointcut等注解,实现灵活的横切逻辑管理。
343 6
AOP 切面编程
|
3月前
|
监控 Java Spring
AOP切面编程快速入门
AOP(面向切面编程)通过分离共性逻辑,简化代码、减少冗余。它通过切点匹配目标方法,在不修改原方法的前提下实现功能增强,如日志记录、性能监控等。核心概念包括:连接点、通知、切入点、切面和目标对象。Spring AOP支持多种通知类型,如前置、后置、环绕、返回后、异常通知,灵活控制方法执行流程。通过@Pointcut可复用切点表达式,提升维护性。此外,结合自定义注解,可实现更清晰的切面控制。
309 5
Micronaut AOP与代理机制:实现应用功能增强,无需侵入式编程的秘诀
AOP(面向切面编程)能够帮助我们在不修改现有代码的前提下,为应用程序添加新的功能或行为。Micronaut框架中的AOP模块通过动态代理机制实现了这一目标。AOP将横切关注点(如日志记录、事务管理等)从业务逻辑中分离出来,提高模块化程度。在Micronaut中,带有特定注解的类会在启动时生成代理对象,在运行时拦截方法调用并执行额外逻辑。例如,可以通过创建切面类并在目标类上添加注解来记录方法调用信息,从而在不侵入原有代码的情况下增强应用功能,提高代码的可维护性和可扩展性。
288 1
|
7月前
|
人工智能 监控 Java
面向切面编程(AOP)介绍--这是我见过最易理解的文章
这是我见过的最容易理解的文章,由浅入深介绍AOP面向切面编程,用科普版和专家版分别解说,有概念,有代码,有总结。
|
安全 Java 编译器
什么是AOP面向切面编程?怎么简单理解?
本文介绍了面向切面编程(AOP)的基本概念和原理,解释了如何通过分离横切关注点(如日志、事务管理等)来增强代码的模块化和可维护性。AOP的核心概念包括切面、连接点、切入点、通知和织入。文章还提供了一个使用Spring AOP的简单示例,展示了如何定义和应用切面。
1364 1
什么是AOP面向切面编程?怎么简单理解?