一、什么是AOP?
即面向切面编程,是对OOP的一种补充和完善,在OOP中由于有大量代码的重复导致不利于各个模块的重用,而AOP技术利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,提升了软件的可操作性和可维护性。
二、Spring AOP 的几个概念
AOP的基本概念
(1)Aspect(切面):定义一个切面类,里面可以定义切入点和Advice(@Before,@After等),是对横切关注点的抽象。
(2)JointPoint(连接点):程序执行过程中明确的点,一般是方法的调用,还可以是字段或则构造器。
(3)Advice(通知):即切入方式是什么,之前?之后?,包含@Before,@After,@AfterReturning,@AfterThrowing,@Around等
(4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
如:下面切入点定义针对所有类名包含Service的类。
<aop:config>
<aop:advisor advice-ref="dataSourceAdvice" pointcut="execution(* com.xxx.lingxu.service..*Service.*(..))" order="1"/>
<aop:advisor advice-ref="txTransactionAdvice" pointcut="execution(* com.xxx.lingxu.service..*Service.*(..)))" order="2" />
</aop:config>
(5)AOP代理:AOP框架创建的对象,代理就是目标对象的加强。Spring中的AOP代理可以使JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类
(6)目标对象:代理的目标对象
(7)Waving(织入):将切面应用到目标对象并导致代理对象创建的过程
(8)Introduction(引入):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
三、@Before与@Around区别
在Spring框架中,使用Aspect-Oriented Programming(AOP)时,@Before
和 @Around
是两种不同类型的通知(Advice),它们定义了切面(Aspect)什么时候以及如何在目标方法(即那些被切面逻辑所"织入"的方法)执行时介入。
@Before
@Before
通知是在目标方法执行之前执行的。当使用 @Before
时,你可以在目标方法实际执行前做一些前置处理,比如日志记录、权限校验等。@Before
通知不能阻止目标方法的执行,除非它抛出了一个异常。
下面是一个使用 @Before
的例子:
@Before("execution(* com.example.service.MyService.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
// 你的代码逻辑,它会在目标方法前执行。
}
在上述代码中,任何 MyService
类下的方法执行之前,beforeAdvice
都会先执行。
@Around
@Around
通知更加强大,它可以在目标方法执行之前和执行之后执行代码,并且可以控制是否执行目标方法。通过 @Around
通知,你可以在方法执行前后添加逻辑,甚至可以决定不执行目标方法,只执行你的切面代码。
@Around
通知需要一个参数 ProceedingJoinPoint
,可以通过调用 ProceedingJoinPoint
的 proceed
方法来执行目标方法。
下面是一个使用 @Around
的例子:
@Around("execution(* com.example.service.MyService.*(..))")
public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
// 在目标方法执行前的代码
try {
Object result = proceedingJoinPoint.proceed(); // 执行目标方法
// 在目标方法执行后的代码
return result;
} catch (Throwable throwable) {
// 异常处理逻辑
throw throwable;
}
}
在上述代码中,你可以在目标方法执行前后添加你自己的逻辑,并且还可以处理方法的返回值。
区别
- 执行时机:
@Before
只在目标方法执行之前运行,而@Around
通知可以在目标方法执行前后都运行。 - 控制权:
@Before
无法控制目标方法的执行(除非抛出异常),而@Around
可以决定是否以及如何执行目标方法。 - 返回值:
@Around
可以访问并修改目标方法的返回值,@Before
则不能。
由于 @Around
通知提供了更多的控制能力,因此它通常用于需要完全覆盖目标方法执行流程的场景,例如事务管理、全面的日志记录等。而 @Before
则更适合执行一些快速的前置校验或简单逻辑。