java - 不能为同一方面类的方法设置建议
问题描述
我正在尝试通过构建小型银行交易模拟来学习带有AspectJ的SpringAOP 。但我无法向方面类本身的方法添加建议(@Before、@After、@AfterThrowing)。
这是模型
银行.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");
}
}
}
这是方面类
银行方面.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();
}
}
这是主要方法
应用程序.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
建议被执行。我想得到“错误的 Pin ”作为输出,但该@AfterThrowing
建议未被识别。
解决方案
该方法public void validatePin()
(在类中BankAspect
)充当建议;因此,如果您AspectJ
单独使用,您将无法以您的方式拦截它(例如,您需要使用切入点adviceexecution
)。在Spring AOP
事情的情况下更加严格;Spring AOP
不允许方面成为建议的目标。
为了解决您的问题,您可以拦截切入点之前被拦截的相同方法,即:
@AfterThrowing("execution(public void dev.ritam.model.Bank.withDraw(..))")
public void logException() {
System.out.println("Wrong Pin");
}
因为异常将在方法范围内引发,所以Bank.withDraw
您的@AfterThrowing
切入点将能够捕获该异常。
仅适用于 AspectJ
一个简单的解决方案是包装此代码:
if (bank.getPinCode() != bank.getTempPin()) {
throw new RuntimeException();
}
进入一个方法,例如:
public void check_pin_code() {
if (bank.getPinCode() != bank.getTempPin()) {
throw new RuntimeException();
}
}
现在拦截该方法:
@AfterThrowing("execution(public void dev.ritam.aspect.BankAspect.check_pin_code(..))")
public void logException() {
System.out.println("Wrong Pin");
}
另一种替代方法,但必须小心使用,将使用adviceexecution()
@AfterThrowing("within(BankAspect) && adviceexecution()")
public void logException() {
System.out.println("Wrong Pin");
}
这将拦截所有在中发生并导致抛出异常的建议执行。BankAspect