首页 > 解决方案 > 不能为同一方面类的方法设置建议

问题描述

我正在尝试通过构建小型银行交易模拟来学习带有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建议未被识别。

标签: javaspringmavendependency-injectionspring-aop

解决方案


该方法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


推荐阅读