Spring AOP编程注解版(SpringBoot)

本文详细介绍了Spring AOP的概念、术语和开发流程,包括连接点、切点、通知等核心概念,并通过实际示例展示了如何进行AOP编程,包括定义切入点、切面、测试环绕通知、获取参数和返回值,以及处理多个切面的执行顺序。通过这些内容,读者可以深入理解Spring AOP的使用方法。

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

AOP的概念

AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子。
具体链接: https://www.cnblogs.com/Wolfmanlq/p/6036019.html

AOP术语
  • 连接点(joint point):对于具体拦截的对象,因为Spring只支持对方法的拦截,所以被拦截的对象通常是指某个特定的方法,也就是我们需要增强的方法。
  • 切点(point cut): :有时候,我 的切面不单单应用于单个方法,也可能是多个类的不同方法,这时,可以通过正则式和指示器的规则去定义,从而适配连接点 切点就是提供这样个功能的概念
  • 通知(advice):就是按照约定的流程下的方法,分为前置通知(before advice)、后置通知(after advice)、环绕通知 (around advice) 事后返回通知( afterRetuming advice )和异常通知(after Throwing advice),它会根据约定织入流程中,需要弄明白它在流程中的顺序和运行条件
  • 目标对象(target):被代理对象
  • 织入 (weaving):它是 个通过动态代理技术,为原有服务对象生成代理对 然后将与切点定义匹配的连接点拦 ,并按约定将各类通知织入约定流程的过
  • 切面(aspect):是 个可以定义切点、各类通知和引入的内 SpringAOP 将通过它的信息来增强 Bea 的功能或者将对应的方法织入流程
AOP开发流程
确认切入点

何 AOP 编程,首先要确 是在什么地方需 AOP ,也就是需要确定连接点(在 Spring中就是什么类的什么方法)的问题,现在我们假设有 UserService 接口

public interface UserService {
	void printUser(User user);
}

对应的实现类

public class UserServiceImpl implements UserService{

	@Override
	public void printUser(User user) {
		// TODO Auto-generated method stub
		if(user == null) {
			throw new RuntimeException("user 不能为空");
		}
		System.out.println(user.getId());
		System.out.println(user.getUsername());
		System.out.println(user.getNote());
	}
}
定义切点和切面
@Component
@Aspect
public class MyAspect {

	// 定义切点
	@Pointcut("execution (* com.sanfeng.aspect.service.Impl.UserServiceImpl.printUser(..))")
	public void pointCut() {

	}
	
	@Before("pointCut()")
	public void before() {
		System.out.println("before method");
	}
	
	@After("pointCut()")
	public void after() {
		System.out.println("After method");
	}
	
	@AfterReturning("pointCut()")
	public void afterReturning() {
		System.out.println("After Returning method");
	}
	
	@AfterThrowing("pointCut()")
	public void afterThrowing() {
		System.out.println("After Throwing method");
	}

}
测试
UserService userService = ioc.getBean(UserService.class);
User user = new User();
user.setId(1L);
user.setNote("note");
user.setUsername("ddd");
userService.printUser(user);
System.out.println(userService);
System.out.println("ddd");

控制台输出
在这里插入图片描述

强大的环绕通知

环绕通知是所有通知中最为强大的通知,强大也意味着难以控制,下面是定义一个环绕通知的代码

@Around("pointCut()")
public void around(ProceedingJoinPoint jp) throws Throwable {
	System.out.println("around before");
	jp.proceed();
	System.out.println("around afreter");
}

环绕通知使用@Around注解,环绕方法有一个ProceedingJoinPoint类型的参数,通过调用其proceed方法可以调用原有目标对象的方法.。
重新测试一下
在这里插入图片描述

通知获取参数

有时候需要在通知中获取目标对象的方法参数,这在Spring中也是允许的。对于非环绕通知可以使用一个连接点(JoinPoint)类型的参数,通过它可以获取参数。

@Before("pointCut()")
public void beforeParam(JoinPoint jp) {
	System.out.println(jp.getArgs()[0] instanceof User);
}
获取返回值

若目标代理对象有返回值,Spring也允许获取返回值

//JoinPoint一定要出现在参数表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
	System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:运行结果:{"+result+"}");
}
多个切面

如果定义多个切面,那么切面的执行顺序回事怎么样的呢?
其实在Spring中,切面的执行顺序是随机的,切面的执行顺序是混乱的,无法通过测试来得知切面的执行顺序,但可以使用Spring的@Order注解来指定切面的优先级,来规定切面的执行顺序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值