第一次的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){
    /* .. */
  }
}

在这个例子中,定义了对于在所有方法中发生的异常进行异常处理。

请提供更多上下文,以便我能够为您提供正确的翻译。

 

广告
将在 10 秒后关闭
bannerAds