拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 在Spring AOP中获取Advised方法信息

在Spring AOP中获取Advised方法信息

白鹭 - 2022-11-26 408 0 0

1.简介

在本教程中,我们将向您展示如何使用Spring AOP方面获取有关方法的签名,参数和注释的所有信息。

2. Maven依赖

让我们从pom.xml添加Spring Boot AOP Starter库依赖关系开始:

<dependency>

 <groupId>org.springframework.bootgroupId>

 <artifactId>spring-boot-starter-aopartifactId>

 dependency>

3.创建切入点注解

让我们创建一个AccountOperation批注。为了澄清,我们将其用作切入点:

@Target(ElementType.METHOD)

 @Retention(RetentionPolicy.RUNTIME)

 public @interface AccountOperation { String operation();

 }

请注意,创建注释对于定义切入点不是强制性的。换句话说,我们可以使用Spring AOP提供的切入点定义语言来定义其他切入点类型,例如类中的某些方法,以某些前缀开头的方法等。

4.创建示例服务

4.1。账户类别

让我们创建一个带有accountNumberbalance属性的Account POJO。我们将其用作服务方法中的方法参数:

public class Account { private String accountNumber; private double balance; // getter / setters / toString

 }

4.2。服务等级

现在,让我们使用两个用@AccountOperation批注进行批注的方法来创建BankAccountService类,以便我们可以获取方面的方法信息。请注意, withdraw方法将引发一个已检查的异常WithdrawLimitException以演示如何获取有关方法抛出的异常的信息。

另外,请注意, getBalance方法没有AccountOperation批注,因此它不会被方面拦截:

@Component

 public class BankAccountService { @AccountOperation(operation = "deposit")

 public void deposit(Account account, Double amount) {

 account.setBalance(account.getBalance() + amount);

 } @AccountOperation(operation = "withdraw")

 public void withdraw(Account account, Double amount) throws WithdrawLimitException { if(amount > 500.0) { throw new WithdrawLimitException("Withdraw limit exceeded.");

 }



 account.setBalance(account.getBalance() - amount);

 } public double getBalance() { return RandomUtils.nextDouble();

 }

 }

5.定义我们的方面

让我们创建一个BankAccountAspect以从BankAccountService:调用的相关方法中获取所有必要的信息BankAccountService:

@Aspect

 @Component

 public class BankAccountAspect { @Before(value = "@annotation(com.baeldung.method.info.AccountOperation)")

 public void getAccountOperationInfo(JoinPoint joinPoint) { // Method Information

 MethodSignature signature = (MethodSignature) joinPoint.getSignature();



 System.out.println("full method description: " + signature.getMethod());

 System.out.println("method name: " + signature.getMethod().getName());

 System.out.println("declaring type: " + signature.getDeclaringType()); // Method args

 System.out.println("Method args names:");

 Arrays.stream(signature.getParameterNames())

 .forEach(s -> System.out.println("arg name: " + s));



 System.out.println("Method args types:");

 Arrays.stream(signature.getParameterTypes())

 .forEach(s -> System.out.println("arg type: " + s));



 System.out.println("Method args values:");

 Arrays.stream(joinPoint.getArgs())

 .forEach(o -> System.out.println("arg value: " + o.toString())); // Additional Information

 System.out.println("returning type: " + signature.getReturnType());

 System.out.println("method modifier: " + Modifier.toString(signature.getModifiers()));

 Arrays.stream(signature.getExceptionTypes())

 .forEach(aClass -> System.out.println("exception type: " + aClass)); // Method annotation

 Method method = signature.getMethod();

 AccountOperation accountOperation = method.getAnnotation(AccountOperation.class);

 System.out.println("Account operation annotation: " + accountOperation);

 System.out.println("Account operation value: " + accountOperation.operation());

 }

 }

请注意,我们将切入点定义为注释,因此BankAccountServicegetBalance方法未使用AccountOperation,注释AccountOperation,因此方面将不会对其进行拦截。

现在,让我们详细分析方面的每个部分,并查看调用BankAccountService方法时在控制台中得到的内容。

5.1。获取有关方法签名的信息

为了获得我们的方法签名信息,我们需要从JoinPoint对像中检索MethodSignature

MethodSignature signature = (MethodSignature) joinPoint.getSignature();



 System.out.println("full method description: " + signature.getMethod());

 System.out.println("method name: " + signature.getMethod().getName());

 System.out.println("declaring type: " + signature.getDeclaringType());

现在让我们调用服务的withdraw()方法:

@Test

 void withdraw() {

 bankAccountService.withdraw(account, 500.0);

 assertTrue(account.getBalance() == 1500.0);

 }

运行withdraw()测试后,我们现在可以在控制台上看到以下结果:

full method description: public void com.baeldung.method.info.BankAccountService.withdraw(com.baeldung.method.info.Account,java.lang.Double) throws com.baeldung.method.info.WithdrawLimitException

 method name: withdraw

 declaring type: class com.baeldung.method.info.BankAccountService

5.2。获取有关参数的信息

要检索有关方法参数的信息,我们可以使用MethodSignature对象:

System.out.println("Method args names:");

 Arrays.stream(signature.getParameterNames()).forEach(s -> System.out.println("arg name: " + s));



 System.out.println("Method args types:");

 Arrays.stream(signature.getParameterTypes()).forEach(s -> System.out.println("arg type: " + s));



 System.out.println("Method args values:");

 Arrays.stream(joinPoint.getArgs()).forEach(o -> System.out.println("arg value: " + o.toString()));

让我们通过调用BankAccountServicedeposit方法来尝试:

@Test

 void deposit() {

 bankAccountService.deposit(account, 500.0);

 assertTrue(account.getBalance() == 2500.0);

 }

这是我们在控制台上看到的:

Method args names:

 arg name: account

 arg name: amount

 Method args types:

 arg type: class com.baeldung.method.info.Account

 arg type: class java.lang.Double

 Method args values:

 arg value: Account{accountNumber='12345', balance=2000.0}

 arg value: 500.0

5.3。获取有关方法注释的信息

我们可以使用Method类的getAnnotation()方法获取有关注释的信息:

Method method = signature.getMethod();

 AccountOperation accountOperation = method.getAnnotation(AccountOperation.class);

 System.out.println("Account operation annotation: " + accountOperation);

 System.out.println("Account operation value: " + accountOperation.operation());

现在,让我们重新运行withdraw()测试并检查我们得到了什么:

Account operation annotation: @com.baeldung.method.info.AccountOperation(operation=withdraw)

 Account operation value: withdraw

5.4。获取其他信息

我们可以获得有关我们方法的其他信息,例如它们的返回类型,它们的修饰符以及它们抛出的异常(如果有):

System.out.println("returning type: " + signature.getReturnType());

 System.out.println("method modifier: " + Modifier.toString(signature.getModifiers()));

 Arrays.stream(signature.getExceptionTypes())

 .forEach(aClass -> System.out.println("exception type: " + aClass));

现在让我们创建一个新的withdrawWhenLimitReached测试,该测试使withdraw()方法超出其定义的提现限制:

@Test

 void withdrawWhenLimitReached()

 {

 Assertions.assertThatExceptionOfType(WithdrawLimitException.class)

 .isThrownBy(() -> bankAccountService.withdraw(account, 600.0));

 assertTrue(account.getBalance() == 2000.0);

 }

现在检查控制台输出:

returning type: void

 method modifier: public

 exception type: class com.baeldung.method.info.WithdrawLimitException

我们的最后一个测试将有助于演示getBalance()方法。如前所述,它不会被方面拦截,因为方法声明中没有AccountOperation批注:

@Test

 void getBalance() {

 bankAccountService.getBalance();

 }

运行此测试时,控制台中没有输出,正如我们期望的那样。

六,结论

在本文中,我们了解了如何获取有关使用Spring AOP方面的方法的所有可用信息。为此,我们定义了一个切入点,将信息打印到控制台中,并检查运行测试的结果。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *