Spring AOP

本文深入解析Spring框架中AOP(面向切面编程)的概念与应用,包括AOP术语、切点选择、通知处理及配置方法。阐述了Spring支持的AOP类型、切点表达式语言及其指示器,并通过实例说明如何在Spring中实现AOP。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Spring对AOP的支持

1. AOP术语

通知(Advice)
Spring切面可以应用5种类型的通知:

  • 前置通知(Before)
  • 后置通知(After)
  • 返回通知(After-returning)
  • 异常通知(After-throwing)
  • 环绕通知(Around)
    连接点(Join point)
    切点(Pointcut)
    切面(Aspect)
    引入(Introduction)
    织入(Weaving)
    在目标对象的生命周期里有多个点可以进行织入:
    • 编译期,AspectJ的织入编译器就是用这种方式
    • 类加载期
    • 运行期,Spring AOP使用此种方式织入切面。

Spring提供了4种类型的AOP支持:

  • 基于代理的经典Spring AOP
  • 纯POJO切面
  • @AspectJ注解驱动的切面
  • 注入式AspectJ切面

Spring只支持方法级别的连接点,不支持字段和构造器接入点。

2、通过切点选择连接点

Spring AOP使用AspectJ的切点表达式语言来定义切点,只支持AspectJ切点指示器的一个子集。下表为支持的指示器:

AspectJ指示器描述
args()限制连接点匹配参数为指定类型的执行方法
@args()限制连接点匹配参数由指定注解标注的执行方法
execution()用于匹配是连接点的执行方法
this()限制连接点匹配AOP代理的bean引用为指定类型的类
target限制连接点匹配目标对象为指定类型的类】
@target()限制连接点匹配特定的执行对象,这些对象对应的类型要具有指定类型的注解
within()限制连接点匹配指定的类型
@within()限制连接点匹配指定注解所标注的类型(当使用Spring AOP时,方法定义在由指定的注解所标注的类里)
@annotation限定匹配带有指定注解的连接点

编写切点
execution(* concert.Performance.perform(..))

* 号表示方法返回值可以是任意类型,然后指定全限定类名和方法名,方法参数列表(..)表明切点要选择任意的perform()方法,无论方法的入参是什么。

execution(* concert.Performance.perform(..)) && within(concert.*)

&&操作符表示同时满足的条件,也可使用||,!操作符 ,within(concert.*)表示当concert包下的任意类的方法被调用时。
xml配置中"&"有特殊含义,可以用andornot代替。

处理通知中的参数

@Pointcut("@execution(* concert.Performance.perform(int) && args(num))")
public void played(int num){}

@Befor("played(num)")
public void countPlayed(int num){
	···
}

agrs(num)表明传递给perform()方法的in类型参数也会传递到通知中去,参数名称与切点方法签名中一致。

开启配置
使用@EnableAspectJAutoProxy启动AspectJ自动代理,配置才能生效
xml使用aop命名空间<aop:aspectj-autoproxy>

通过注解引入新功能

@Aspect
public class EncoreableINtroducer(){
	@DeclareParents(value="concert.Performance+",defaultImpl=DefaultEncoreable.class)
	public static Encoreable encoreable;
}

EncoreableINtroducer 是一个切面,通过 DeclareParents 注解,将 Encoreable 接口引入到Perfirmance bean中。DeclareParents 由三部分组成:

  • value 指定哪种类型的bean需要引入该接口,Performance+中的+表示所有子类型,而不是其本身。
  • defaultImpl 指定为引入功能提供实现的类。
  • @DeclareParents注解所标注的静态属性指明了要引入的接口。

xml中声明切面
Spring aop配置元素能够以非入侵方式声明切面

AOP配置元素用途
<aop:adviser>定义aop通知器
<aop:after>定义后置通知(不管被通知的方法是否执行成功)
<aop:after-returning>定义aop返回通知
<aop:after-throwing>定义aop异常通知
<aop:around>定义aop环绕通知
<aop:aspect>定义一个切面
<aop:aspect-autoproxy>启用@AspectJ注解驱动的切面
<aop:before>定义aop前置通知
<aop:config>顶层的AOP元素。大多<aop:*>元素必须包含在<aop:config>内
<aop:declare-parents>以透明的方式为被通知的对象引入额外的接口
<aop:pointcut>定义一个切点

声明一个没有注解的bean为切面

<aop:config>
    <!--引用一个bean声明为切面-->
	<aop:aspect ref="audience">
	<aop:before pointcut="execution(* concert.Performance.perform(..))" method="dobefore" />
</aop:config>

使用<aop:pointcut>定义命名切点

<aop:config>
    <!--引用一个bean声明为切面-->
	<aop:aspect ref="audience">
	<!--定义切点-->
	<aop:pointcut id="performance" expression="execution(* concert.Performance.perform(..))">
	<aop:before pointcut-ref="performance" method="dobefore" />
</aop:config>
###Spring AOP 的概念 AOP(Aspect-Oriented Programming)即面向切面编程,是一种编程范式,旨在通过分离横切关注点来提高模块化程度。在 Spring 框架中,AOP 被广泛用于实现诸如日志记录、事务管理、安全性等通用功能,这些功能通常与业务逻辑无关但又需要在多个地方重复使用。 Spring AOP 主要是基于 AspectJ 实现的,尽管 AspectJ 是一个独立的 AOP 框架,并不是 Spring 的组成部分,但它通常与 Spring 一起使用以提供更强大的 AOP 功能[^1]。Spring AOP 支持两种方式来定义切面:基于 XML 配置文件的方式和基于注解的方式。 ###Spring AOP 的原理 Spring AOP 使用运行时代理来实现 AOP 功能,这意味着它会在运行时动态生成代理对象。对于实现了接口的类,Spring AOP 默认使用 JDK 动态代理;而对于没有实现接口的类,则会使用 CGLIB 代理[^4]。这种方式允许在不修改原始代码的情况下向程序中添加新的行为。 织入(Weaving)是将增强(advice)应用到目标对象的过程,Spring AOP 在运行时进行织入操作[^3]。当创建了代理对象后,所有对目标对象方法的调用都会被拦截,并且可以插入额外的操作,比如在方法执行前后做一些处理。 ###Spring AOP 的使用教程 要开始使用 Spring AOP,首先需要确保项目中包含了必要的依赖。如果使用 Maven 构建工具,可以在 `pom.xml` 文件中加入如下依赖: ```xml <!-- 引入aop依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> ``` 一旦添加了依赖并刷新了 Maven 项目,就可以开始编写切面了。下面是一个简单的例子,展示如何使用注解来定义一个切面: ```java import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { @Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Method " + joinPoint.getSignature().getName() + " is called."); } } ``` 在这个示例中,`LoggingAspect` 类被标记为 `@Aspect` 和 `@Component` 注解,这样 Spring 就能识别这是一个切面组件。`@Before` 注解指定了在哪些方法上应用前置通知(before advice),这里的表达式表示匹配 `com.example.service` 包下所有的方法。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值