第一次的Spring AOP
这次我想写关于Spring AOP的内容。
如果你想了解详细规格,请阅读官方参考文档。
版本是Spring Boot 2.0.1.RELEASE(Spring 5.0.5.RELEASE)。
AOP是什么?
AOP是Aspect Oriented Programming的缩写,被称为”面向切面编程”。
在AOP中,我们通过编写代码将横跨类的处理(如异常处理、日志记录、事务处理等)与业务逻辑分离。通过这样做,我们可以简洁地编写多个处理,并防止相同的处理在各个地方被重复编写。
春天面向切面编程的术语
-
- Aspect
-
- JoinPoint
-
- PointCut
- Advice
方面
Aspect指的是定义了横向处理和执行位置的模块。
在Spring中,通过给类添加@Aspect注解,该类将被认为是一个Aspect。
需要将Aspect定义为Bean,所以不要忘记添加@Component注解将其声明为Bean。
@Component
@Aspect
public class HogeAspect{
}
加入点
JoinPoint是指插入横切性处理的位置(方法)。
切入点
PointCut是表示JoinPoint的集合的概念。
它可以用作Advice(稍后解释)注解参数中的PointCut表达式。
在下面的代码示例中,我们使用execution()指定了JoinPoint。
@After(value = "execution(* com.example.fuga..Fuga.*(..))")
public void Hoge(/* .. */){
/* .. */
}
/* Springでは、他のパラメータがない場合、valueという名前のパラメータの「value =」は省略できるので、
@After("execution(* com.example.fuga..Fuga.*(..))") と書くこともできます。*/
在execution()中,JoinPoint以以下的语法表示。
execution(戻り値 パッケージ名.クラス名.メソッド名(引数の型))
/*
「*」 -> 任意の文字列を表す。ただし、パッケージ名で使う場合は、「任意の名前の1パッケージ」を表し、引数で使う場合は「任意の型1つ」を表す。
「..」 -> パッケージ名で使う場合は、「0以上のパッケージ」を表し、引数で使う場合は「0以上の任意の型」を表す。
*/
在最开始提到的例子中,表达的是对于位于任意返回类型的”com.example.fuga”包以及其子包下的”Fuga”类的所有方法都应用@After注解。
除了execution()之外,还有within()、this()等等各种选项,但常常使用execution()。参考
建议 yì)
通过在带有@Aspect注解的类的方法上添加注解,可以将该方法作为Advice执行。Advice是表示在JoinPoint上执行的跨切面处理本身。Advice的注解类型有以下五种。
在之前
这是在执行目标方法之前执行的Advice。
@Before("execution(* *..*(..))")
public void beforeHandler(){
/* .. */
}
@之后
无论方法的处理结果如何,都会被执行的Advice。
@After("execution(* *..*(..))")
public void afterHandler(){
/* .. */
}
@返回之后
只有当目标方法的处理正确地结束时才会执行的Advice。
如果在returning参数中指定了一个字符串,那么该字符串的变量将保存由JoinPoint执行的处理的返回值。这样就可以在Advice中使用返回值。
@AfterReturning(value = "execution(* *..*(..))", returning = "r")
public void afterReturning(Object r){
System.out.println(r);
}
@抛出异常之后
这是一个只有在目标方法处理过程中发生异常时才会执行的Advice。
如果通过throwing参数指定了一个字符串,那么该字符串变量将存储在JoinPoint中发生的异常信息,从而可以在Advice中使用该异常信息。
@AfterThrowing(value = "execution(* *..*(..))", throwing = "e")
public void afterThrowing(Throwable e){
System.out.println(e.getMessage());
}
@周围
这是一种可以在目标方法的处理前、处理后等任意时机执行的Advice。
您可以像下面的示例一样自由设置前处理和后处理。
@Around("execution(* *..*(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("前処理")
//メソッド実行
Object result = pjp.proceed();
System.out.println("後処理")
}
使用方法 (shǐ fǎ)
在pom.xml中添加库
如果使用Spring Boot,需要在pom.xml文件的dependencies中添加”spring-boot-starter-aop”。如果已经将”spring-boot-starter-parent”指定为parent,那么无需指定spring-boot-starter-aop的版本信息,因为已经定义了版本信息。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
如果你不使用Spring Boot,只需将”spring-aop”和”aspectjweaver”添加到pom.xml中,并在JavaConfig上加上@EnableAspectJAutoProxy,就可以使用它(未经验证)。
创建一个Aspect
创建一个用于Aspect的类,并在该类的首行添加@Aspect和@Component标记。
@Component
@Aspect
public class HogeAspect{
}
撰写建议并描述切点(PointCut)。
为定义为Aspect的类创建方法。
根据Advice执行的时机,请在上述Advice的注释中适当添加注解。
此外,使用Advice的注解中的execution()描述要将Advice应用于哪个类或方法。
@Component
@Aspect
public class HogeAspect{
@AfterThrowing(value = "execution(* *..*(..))", throwing = "ex")
public void handler(Throwable ex){
/* .. */
}
}
在这个例子中,定义了对于在所有方法中发生的异常进行异常处理。
请提供更多上下文,以便我能够为您提供正确的翻译。