gpt4 book ai didi

java - 不能为同一方面类的方法设置建议

转载 作者:行者123 更新时间:2023-12-04 08:30:49 24 4
gpt4 key购买 nike

我正在尝试与 一起学习 SpringAOP AspectJ ,通过建立一个小型银行交易模拟。但是我无法向方面类本身的方法添加建议(@Before、@After、@AfterThrowing)。
这是模型

Bank.java

@Component
public class Bank {
private int balance;
private int pinCode;
private int tempPin;

public int getBalance() {
return balance;
}

@Value("10000")
public void setBalance(int balance) {
this.balance = balance;
}

public int getPinCode() {
return pinCode;
}

@Value("6789")
public void setPinCode(int pinCode) {
this.pinCode = pinCode;
}

public int getTempPin() {
return tempPin;
}

public void setTempPin(int tempPin) {
this.tempPin = tempPin;
}

public void withDraw(int amount) {
if (amount <= balance) {
balance -= amount;
System.out.println("Successful Withdraw");
} else {
System.out.println("Insufficient Balance");
}
}
}

这是方面类

BankAspect.java

@Component
@Aspect
public class BankAspect {
private Bank bank;

public Bank getBank() {
return bank;
}

@Autowired
public void setBank(Bank bank) {
this.bank = bank;
}

@Before("execution(public void dev.ritam.model.Bank.withDraw(..))")
public void validatePin() {
if (bank.getPinCode() != bank.getTempPin()) {
throw new RuntimeException();
}
}

@AfterThrowing("execution(public void dev.ritam.aspect.BankAspect.validatePin(..))")
public void logException() {
System.out.println("Wrong Pin");
}
}
这是配置类

AppConfig.java

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("dev.ritam")
public class AppConfig {
@Bean
Bank bank() {
return new Bank();
}

@Bean
BankAspect bankAspect() {
return new BankAspect();
}
}
这是主要方法

App.java

public class App {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
Bank bank = context.getBean(Bank.class);

try {
bank.setTempPin(1234);
bank.withDraw(1000000);
} catch (Exception ignore) {
}
}
}

只有 validatePin() @Before建议正在执行。我想得到“错误的引脚”作为输出,但是 @AfterThrowing建议不被认可。

最佳答案

来自引用 documentation :

Advising aspects with other aspects?In Spring AOP, aspects themselvescannot be the targets of advice from other aspects. The @Aspectannotation on a class marks it as an aspect and, hence, excludes itfrom auto-proxying.


您不能在 Spring AOP 中建议方面,这就是 @AfterThrowing 的原因。不执行。
要抛出异常并记录消息,您可以建议相同的方法 Bank.withDraw()@AfterThrowing .这样, validatePin()建议将在 Bank.withDraw() 之前执行和 logException()如果验证抛出异常,则建议将被执行。这是@dreamcash 的回答中提到的第二个选项。
示例代码
@Before("execution(public void dev.ritam.model.Bank.withDraw(..))")
public void validatePin() {
if (bank.getPinCode() != bank.getTempPin()) {
throw new RuntimeException();
}
}

@AfterThrowing("execution(public void dev.ritam.model.Bank.withDraw(..))")
public void logException() {
System.out.println("Wrong Pin");
}
这将导致以下控制台输出序列
Wrong Pin
java.lang.RuntimeException
需要考虑的几点。 BankBankAspect@Component 注释和 @ComponentScan会将它们注册为 bean。这意味着在 @Bean 注册的 bean在 AppConfig 中不是必需的。两者中的任何一个都是必需的。
@dreamcrash 的回答中提到的最后一个选项不支持通过 Spring AOP : 请参阅以 开头的部分其他切入点类型
更新 :
这是一个棘手的问题,我建议的答案是基于
Spring Boot 版本:2.2.6.RELEASE
它使用来自版本的 spring 库:5.2.5.RELEASE
code shared by OP 基于 Spring 版本:5.3.1 并且建议未按预期执行。
共享代码中的 Spring AOP 建议按预期工作,spring 版本应 <= 5.2.6.RELEASE
请更新 pom.xml 条目
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
为了快速引用,以下是不适用于版本 5.3.1 的 OP 代码
@After("execution(public void dev.ritam.model.Bank.setTempPin(..))")
public void validatePin() {
if (bank.getPinCode() != bank.getTempPin()) {
throw new RuntimeException("Wrong Pin");
} else {
System.out.println("Correct Pin");
}
}

@AfterThrowing(value = "execution(public void dev.ritam.model.Bank.setTempPin(..))", throwing = "e")
public void logException(Exception e) {
System.out.println(e.getMessage());
}
不确定这种行为变化是否被记录在案,或者这是一个错误。
如果我发现任何有关此的更多信息,将更新。
信息:
这似乎是一个框架问题。更多细节在这里:
https://github.com/spring-projects/spring-framework/issues/26202
来自 reference documentation 的相关信息,

As of Spring Framework 5.2.7, advice methods defined in the same@Aspect class that need to run at the same join point are assignedprecedence based on their advice type in the following order, fromhighest to lowest precedence: @Around, @Before, @After,@AfterReturning, @AfterThrowing. Note, however, that due to theimplementation style in Spring’s AspectJAfterAdvice, an @After advicemethod will effectively be invoked after any @AfterReturning or@AfterThrowing advice methods in the same aspect.

关于java - 不能为同一方面类的方法设置建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65032499/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com