最新最全面的Spring详解(四)——面向切面编程(上)

简介: 最新最全面的Spring详解(四)——面向切面编程(上)

一、AOP 概述


1️⃣什么是AOP


面向切面编程(AOP)通过提供另一种考虑程序结构的方法对面向对象编程(OOP)进行了补充。


OOP中模块化的关键单元是类,而AOP中模块化的关键单元是aspect(切面)。

Spring的关键组件之一是AOP框架。 虽然Spring IoC容器不依赖于AOP(这意味着如果您不想使用AOP就不需要),但AOP对Spring IoC进行了补充,提供了一个非常强大的企业级解决方案。


b18d4a6593834e02b07ce2948ab925eb.png

这里有几个名词需要了解一下:


aop alliance:是AOP联盟,该组织定义了很多针对面向切面的接口api,通常Spring等其它具备动态织入功能的框架依赖此包。


AspectJ:AOP虽然是方法论,但就好像OOP中的Java一样,一些先行者也开发了一套语言来支持AOP。目前用得比较火的就是AspectJ语言了,它是一种几乎和Java完全一样的语言,而且完全兼容Java。当然spring也有独立的AOP的实现。


2️⃣AOP相关术语


Aspect(切面): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。


Join point(连接点 ): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。


Advice(通知): 在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。通知的类型将在后面部分进行讨论。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。


Pointcut(切入点 ): 匹配连接点(Joinpoint)的断言。通知和一个【切入点表】达式关联,并在满足这个切入点的连接点上运行。【切入点表达式如何和连接点匹配】是AOP的核心:Spring缺省使用AspectJ切入点语法。


Introduction(引入): Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。


Target object(目标对象): 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做被通知(advised) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。


AOP代理 AOP proxy: 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

Weaving(织入): 把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,这个过程叫织入。这些可以在编译时(例如使用AspectJ编译器),类加载时和运行时完成。 Spring和其他纯Java AOP框架一样,在运行时完成织入。


3️⃣Spring AOP通知类型


Before advice : 在连接点之前运行的通知,但不能阻止执行流继续执行到连接点(除非它抛出异常)。


After returning advice : 在连接点正常完成后运行的通知(例如,如果方法返回而不引发异常)。


After throwing advice: 在方法通过抛出异常退出时运行的通知。


After (finally) advice: 不管连接点以何种方式退出(正常或异常返回),都要运行的通知。

Around advice: 围绕连接点(如方法调用)的通知。 这是最有力的建议。 Around通知可以在方法调用前后执行自定义行为。它还负责选择是继续到连接点,还是通过返回自己的返回值或抛出异常来简化被通知的方法执行。


二、Spring AOP能力和目标


Spring AOP是用纯Java实现的。 不需要特殊的编译过程。


Spring AOP目前只支持【方法执行连接点】(在Spring bean上的方法上执行通知)。

如果需要通知字段访问和更新连接点,可以考虑使用AspectJ之类的语言。

Spring AOP的AOP方法不同于大多数其他AOP框架。 目的不是提供最完整的AOP实现(尽管Spring AOP很有能力)。


相反,其目的是提供AOP实现和Spring IoC之间的紧密集成,以帮助解决企业应用程序中的常见问题。

Spring和AspectJ


Spring框架的AOP功能通常与Spring IoC容器一起使用。 切面是通过使用普通beanDifination语法配置的。


使用Spring AOP不能轻松或有效地完成一些事情,比如通知非常细粒度的对象(通常是域对象)。 AspectJ是这种情况下的最佳选择。然而,我们的经验是,Spring AOP为企业Java应用程序中的大多数问题提供了一个很好的解决方案。


Spring AOP从不与AspectJ竞争,以提供全面的AOP解决方案。 我们相信基于代理的框架(如Spring AOP)和成熟的框架(如AspectJ)都是有价值的,它们是互补的,而不是相互竞争的。 Spring无缝地将Spring AOP和IoC与AspectJ集成在一起,以支持在一致的基于Spring的应用程序体系结构中使用AOP。 这种集成不会影响Spring AOP API或AOP Alliance API, Spring AOP保持向后兼容。


三、AOP代理


Spring AOP默认为AOP代理使用标准的JDK动态代理, 这允许代理任何接口(或接口集)。

Spring AOP也可以使用CGLIB代理。 缺省情况下,如果业务对象没有实现接口,则使用CGLIB。

由于编写接口是很好的实践,因此业务类通常实现一个或多个业务接口是可能的。


四、@AspectJ风格的支持


@AspectJ是将【切面】声明为带有注解的常规Java类的一种风格。 @AspectJ风格是由AspectJ项目作为AspectJ 5发行版的一部分引入的。 Spring与AspectJ 5有相同的注解, 但是,AOP运行时仍然是纯Spring AOP,并且不依赖于AspectJ编译器或编织器。


1️⃣对于 @AspectJ的支持


要在Spring配置中使用@AspectJ注解,您需要启用Spring支持,以便基于@AspectJ注解配置Spring AOP,如果Spring确定一个bean被一个或多个切面通知,它将自动为该bean生成一个代理,以拦截方法调用,并确保通知在需要时运行。


@AspectJ支持可以通过XML或java的配置来启用。 在这两种情况下,你还需要确保【AspectJ的’ aspectjweaver.jar ‘库】在你的应用程序的类路径上(1.8或更高版本)。 这个库可以在AspectJ发行版的’ lib '目录中或Maven中央存储库中获得。


🍀使用Java配置启用@AspectJ支持


要使用Java的【@Configuration】启用@AspectJ支持,请添加【@EnableAspectJAutoProxy】注解,如下面的示例所示:


@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
}

🍀使用XML配置启用@AspectJ支持,请使用<aop:aspectj-autoproxy/>元素,如下例所示:

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!-- bean definitions here -->
  <aop:aspectj-autoproxy/>
</beans>


当然,我们需要引入aop的命名空间。


2️⃣声明一个切面


启用@AspectJ支持后,在应用程序上下文中定义的任何带有@AspectJ注解类的bean都会被Spring自动检测并用于配置Spring AOP。


两个示例中的第一个展示了应用程序上下文中的常规beanDifination,它指向一个具有“@Aspect”注解的bean类:

<bean id="myAspect" class="org.xyz.NotVeryUsefulAspect">
    <!-- configure properties of the aspect here -->
</bean>

两个示例中的第二个展示了’ NotVeryUsefulAspect ‘类定义,它是用’ org.aspectj.lang.annotation '标注的。 方面的注解;

package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class NotVeryUsefulAspect {
}

用“@Aspect”标注的类可以有方法和字段,与任何其他类一样。 它们还可以包含切入点、通知和引入(类型间)声明。


通过组件扫描自动检测切面你可以在Spring XML配置中通过“@Configuration”类中的“@Bean”方法将切面类注册为常规bean,或者让Spring通过类路径扫描自动检测它们——就像任何其他Spring管理的bean一样。 但是,请注意,“@Aspect”注解不足以实现类路径中的自动检测。 为了达到这个目的,您需要添加一个单独的【@Component】注解。


在Spring AOP中,切面本身不能成为来自其他通知的目标。 类上的“@Aspect”注解将其标记为一个切面类,因此会将其排除在自动代理之外。


3️⃣声明一个切入点


【切入点确定感兴趣的连接点】,从而使我们能够控制通知何时运行。


切入点声明由两部分组成:包含【名称和方法签名】,以及确定我们感兴趣的方法执行的【切入点表达式】。


怎么确定一个方法:public void com.ydlclass.service.impl.*(…)

@Pointcut("execution(* transfer(..))") // the pointcut expression
private void anyOldTransfer() {} // the pointcut signature

🍀支持切入点指示器


Spring AOP支持以下在切入点表达式中使用的AspectJ切入点指示器(PCD):


  • execution:(常用)用于匹配方法执行的连接点,这是在使用Spring AOP时使用的主要切入点指示符。(匹配方法)

275e95b7d1004be486124f8ec86040da.png

within: 用于匹配指定类型内的方法执行。(匹配整个类)


a0be56665e4645ec8708dd549a19a87b.png


this: 用于匹配当前【AOP代理对象】类型的执行方法;注意是AOP代理对象的类型匹配,这样就可能【包括引入接口】也进行类型匹配。(配置整个类)


05ff8170b3c04fb78b99f17382727bac.png


target: 用于匹配当前目标对象类型的执行方法;注意是目标对象的类型匹配,这样就【不包括引入接口】也进行类型匹配。(配置整个类)

889de56656dc4f93971a3cc2931ac8f9.png

args: 限制匹配连接点(使用Spring AOP时的方法执行),其中参数是给定类型的实例。 (参数类型匹配)

4ed05424f1fd475a96b66816a9e9e86f.png

@target: 用于匹配当前目标对象类型的执行方法,其中目标对象持有指定的注解 。(类上的注解)

21c10b67f2984be4bb39ff28233b03b9.png

@args: 用于匹配当前执行的方法传入的参数持有指定注解的执行。(参数上的注解)


5ca4e8910cd542a7a1f78db991c9ce13.png

@within: 用于匹配所有持有指定注解类型内的方法。(类上的注解)


14b10fbcfa0d48d09c155620338ecc8c.png

@annotation: (常用)于匹配当前执行方法持有指定注解的方法。(方法上的注解)



b597656a94cb42d6921ac8b886765fdb.png


bean:使用“bean(Bean id或名字通配符)”匹配特定名称的Bean对象的执行方法;Spring ASP扩展的,在AspectJ中无相应概念。


e7b0aa9502ba4d8b858f85a64d1ead08.png


相关文章
|
3天前
|
Java Spring
一键注入 Spring 成员变量,顺序编程
介绍了一款针对Spring框架开发的插件,旨在解决开发中频繁滚动查找成员变量注入位置的问题。通过一键操作(如Ctrl+1),该插件可自动在类顶部添加`@Autowired`注解及其成员变量声明,同时保持光标位置不变,有效提升开发效率和代码编写流畅度。适用于IntelliJ IDEA 2023及以上版本。
一键注入 Spring 成员变量,顺序编程
|
2月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
31 1
|
2月前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
55 0
|
4月前
|
XML Java 数据格式
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
这篇文章是Spring5框架的AOP切面编程教程,通过XML配置方式,详细讲解了如何创建被增强类和增强类,如何在Spring配置文件中定义切入点和切面,以及如何将增强逻辑应用到具体方法上。文章通过具体的代码示例和测试结果,展示了使用XML配置实现AOP的过程,并强调了虽然注解开发更为便捷,但掌握XML配置也是非常重要的。
Spring5入门到实战------11、使用XML方式实现AOP切面编程。具体代码+讲解
|
4月前
|
Java Spring XML
掌握面向切面编程的秘密武器:Spring AOP 让你的代码优雅转身,横切关注点再也不是难题!
【8月更文挑战第31天】面向切面编程(AOP)通过切面封装横切关注点,如日志记录、事务管理等,使业务逻辑更清晰。Spring AOP提供强大工具,无需在业务代码中硬编码这些功能。本文将深入探讨Spring AOP的概念、工作原理及实际应用,展示如何通过基于注解的配置创建切面,优化代码结构并提高可维护性。通过示例说明如何定义切面类、通知方法及其应用时机,实现方法调用前后的日志记录,展示AOP在分离关注点和添加新功能方面的优势。
61 0
|
4月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
56 0
|
4月前
|
Java Spring 供应链
Spring 框架事件发布与监听机制,如魔法风暴席卷软件世界,开启奇幻编程之旅!
【8月更文挑战第31天】《Spring框架中的事件发布与监听机制》介绍了Spring中如何利用事件发布与监听机制实现组件间的高效协作。这一机制像城市中的广播系统,事件发布者发送消息,监听器接收并响应。通过简单的示例代码,文章详细讲解了如何定义事件类、创建事件发布者与监听器,并确保组件间松散耦合,提升系统的可维护性和扩展性。掌握这一机制,如同拥有一把开启高效软件开发大门的钥匙。
50 0
|
5月前
|
Java Spring 容器
Spring问题之Spring AOP是如何实现面向切面编程的
Spring问题之Spring AOP是如何实现面向切面编程的
|
4月前
|
XML Java 数据库
Spring5入门到实战------10、操作术语解释--Aspectj注解开发实例。AOP切面编程的实际应用
这篇文章是Spring5框架的实战教程,详细解释了AOP的关键术语,包括连接点、切入点、通知、切面,并展示了如何使用AspectJ注解来开发AOP实例,包括切入点表达式的编写、增强方法的配置、代理对象的创建和优先级设置,以及如何通过注解方式实现完全的AOP配置。
|
5月前
|
设计模式 缓存 程序员
Spring6(三):面向切面AOP(1)
Spring6(三):面向切面AOP(1)
37 1