Springboot使用切面功能详解
作者:逐光猴
Spring切面功能介绍
Spring Boot 是一个基于Spring框架的项目,它简化了基于Spring的应用开发。在Spring框架中,切面(Aspect)是一种特殊的类,它定义了横切关注点(cross-cutting concerns),比如日志记录、事务管理、权限检查等。这些关注点通常横跨多个请求处理路径,因此被称为“横切”关注点。
AOP在spring中又叫“面向切面编程”,它可以说是对传统我们面向对象编程的一个补充,从字面上顾名思义就可以知道,它的主要操作对象就是“切面”,所以我们就可以简单的理解它是贯穿于方法之中,在方法执行前、执行时、执行后、返回值后、异常后要执行的操作。 相当于是将我们原本一条线执行的程序在中间切开加入了一些其他操作一样。
下面这个图就展示了切面的样子。我们定义了日志切面、安全切面等,可以实现统一的日志管理和安全管理。请求来了之后,先依次通过各个切面,然后调用业务逻辑。返回的时候再次通过各个切面。切面的好处我认为在两个方面:1) 不侵入现有的业务代码 2)一个切面的代码,可以实现对多个业务模块进行处理,提升了代码复用性。
切面定义和使用流程
在Spring框架中,切面是通过使用AOP(面向切面编程)来实现的。Spring AOP提供了一个强大而灵活的机制来实现切面。以下是在Spring Boot中使用切面的一些基本概念和步骤:
引入依赖 :
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
定义切面(Aspect) :
创建一个类,使用@Aspect
注解来声明它是一个切面。
切点(Pointcut) :
使用@Pointcut
注解来定义一个切点,它指定了哪些方法将被切面拦截。
通知(Advice) :
定义通知,它指定了在切点处应该执行什么操作。有不同类型的通知,包括:
@Before
:在目标方法执行之前执行。@After
:在目标方法执行之后执行。@AfterReturning
:在目标方法成功返回后执行。@AfterThrowing
:在目标方法抛出异常后执行。@Around
:在目标方法执行前后都执行。
织入(Weaving) :
织入是将切面应用到目标对象的过程。Spring AOP通过代理机制来实现织入。
启用AOP:
在Spring Boot应用中,你可以通过在启动类上添加@EnableAspectJAutoProxy
注解来启用AOP。
下面是一个简单的Spring Boot切面示例,实现了日志的切面功能:
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect // 声明这是一个切面类 @Component // 让Spring容器接管 public class LoggingAspect { // 定义切点,拦截com.example包及其子包下的所有方法 @Pointcut("within(com.example..*)") public void loggable() {} // 定义一个前置通知 @Before("loggable()") public void beforeAdvice() { System.out.println("Before the method is called"); } ``` // 方法正常执行完之后 /** * 在程序正常执行完之后如果有返回值,我们可以对这个返回值进行接收 * returning用来接收方法的返回值 * */ @AfterReturning("loggable()",returning="result") public void LogReturn(JoinPoint joinPoint,Object result) { System.out.println("【" + joinPoint.getSignature().getName() + "】程序方法执行完毕了...结果是:" + result); } }
在这个例子中,LoggingAspect
类定义了一个切点loggable
,它拦截com.example
包及其子包下的所有方法。beforeAdvice
方法是一个前置通知,它会在匹配的每个方法执行之前被调用。
JointPoint可以获得方法的相关信息,如方法的返回值、方法名、参数类型等。
要使用这个切面,你需要在Spring Boot的主类上添加@EnableAspectJAutoProxy
注解:
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }
这种方式下,除非你对项目代码特别熟悉,才知道哪里定义了切面的功能,对哪些类起作用。
否则,如果你是接手一个新的项目,或者一个开源项目,梳理清楚这些关系还是比较麻烦的。我觉得切面结合注解来使用,可能更好一些。
切面结合注解使用
在Spring框架中,切面(Aspect)可以与注解(Annotation)结合使用,以提供更灵活的横切关注点处理。通过注解,你可以在代码中直接指定哪些方法需要被特定的切面处理,而不需要在切面中硬编码方法名或类名。这种方式使得代码更加清晰,并且易于维护。
以下是如何结合注解使用切面的步骤:
1. 定义注解
首先,你需要定义一个注解,这个注解将被用来标记需要被切面处理的方法。
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD}) // 这个注解只能应用至方法上 @Retention(RetentionPolicy.RUNTIME) // 运行时还会保留这个注解 public @interface Loggable { }
2. 创建切面
然后,创建一个切面类,并在其中定义一个切点(Pointcut),这个切点将匹配所有标记了@Loggable
注解的方法。
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { // 定义切点,匹配所有标记了@Loggable注解的方法 @Pointcut("@annotation(com.example.Loggable)") public void loggable() {} // 定义一个前置通知 @Before("loggable()") public void beforeAdvice(JoinPoint joinPoint) { // 这里利用了JAVA反射的特性 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Loggable loggable = signature.getMethod().getAnnotation(Loggable.class); if (loggable != null) { System.out.println("Before method: " + joinPoint.getSignature().getName() + " - " + loggable); } } }
在这个例子中,loggable
切点匹配所有标记了@Loggable
注解的方法。beforeAdvice
方法是一个前置通知,它会在每个标记了@Loggable
注解的方法执行之前被调用。
3. 使用注解
最后,在你的业务逻辑中,使用@Loggable
注解来标记需要被切面处理的方法。
import com.example.Loggable; import org.springframework.stereotype.Service; @Service public class MyService { @Loggable public void someMethod() { System.out.println("Executing someMethod"); } }
在这个例子中,someMethod
方法被标记了@Loggable
注解,因此它会被LoggingAspect
中的beforeAdvice
方法拦截。
4. 启用AOP
确保你的Spring Boot应用已经启用了AOP,如之前所述,可以在启动类上添加@EnableAspectJAutoProxy
注解。
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.EnableAspectJAutoProxy; @SpringBootApplication @EnableAspectJAutoProxy public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }
通过这种方式,你可以灵活地使用注解来控制哪些方法需要被切面处理,而不需要在切面中硬编码方法名或类名,使得代码更加模块化和易于维护。
以上就是Springboot使用切面功能详解的详细内容,更多关于Springboot切面的资料请关注脚本之家其它相关文章!