【问题标题】:bank account program using aspectj使用aspectj的银行账户程序
【发布时间】:2020-04-23 23:44:44
【问题描述】:

我想编写一个跟踪银行帐户的 java 程序

现在我有以下简单的程序:

public class account
{
    private double balance;
    private String owner;
    public account(double x, String s) { balance=x; owner=s; }
    public String owner() { return owner; }
    public void withdraw(double a) { balance -= a; }
    public void deposit(double a) { balance += a; }
    public void printbalance() { System.out.println(balance); }

    // main for testing:
public static void main(String[] argv)
{
      account a1 = new account(2000,"you boss");
      account a2 = new account(1000,"me nerd");
      a1.deposit(400);
      a2.withdraw(300000);   // not enough money!
      a2.withdraw(-500000); // trying to cheat!
      a1.printbalance();
      a2.printbalance();
}//main
} // account

我想使用 aspectj 在这个程序中添加以下内容:

1-我想阻止账户提取更多的当前余额并提取负数。

2- 我也希望它防止存入负数。

3- 我需要添加一个图形界面,(按钮)

4- 添加在客户进行交易之前需要输入的密码或密码。

5- 跟踪账户上的所有交易(提款和存款),并在需要时打印报告。

感谢您的帮助。谢谢。

privileged aspect newAccount
{
  //withdraw (prevent withdraw negative numbers and number greater than the   //current balance) 
    void around(account a, double x) : execution(void account.withdraw(double)) && target(a) && args(x){
        if(x > a.balance){
            System.out.println("not enough money!");
            return;
        }else if(x < 0){
            System.out.println("trying to cheat!");
            return;
        }
        proceed(a, x);
    }

//Deposit: prevent deposit negative number
    void around(double x) : execution(void account.deposit(double)) && args(x){
        if(x < 0){
            System.out.println("trying to  deposit negtive money!");
            return;
        }
        proceed(x);
    } 

    after() : execution(public static void *.main(String[])){
        account.a3 = new account(3000,"he nerd");
        a3.deposit(-100);
        a3.printbalance();

    }

//To Do: pin secret password 
//To Do: Transaction Record
}

【问题讨论】:

  • 1、2 和 4 和 5 级可以在没有 AOP 的情况下做得更好。我不知道 AspectJ 对 3 有什么用处。如果您只想练习 AspectJ,official documentation 中有一些示例可以帮助您入门。
  • 我不同意。我会排除 3,因为 GUI 不是一个方面。但是1、2、4、5可以通过AOP实现(当然也可以不用)。至于 GUI,也许 GUI 和后端之间的通信(通知、事件)也可以通过 AOP 完成。但是,让我们跳过自以为是的讨论,直奔主题:我是否正确地假设这是某种家庭作业,而它的全部意义在于使用 AOP?
  • 是的,大部分。 @kriegaex
  • 那么你尝试了什么,你的问题在哪里?请显示一些方面的代码。或者您是否希望这里有人为您完成家庭作业?你可以付钱给我,但我有一种感觉,你宁愿免费获得信息,最好不要自己做任何工作。
  • 我添加了我到目前为止所做的事情。对造成的不便表示歉意。我只是想了解aspectj,因为我还在学习Java。我将不胜感激任何帮助。谢谢你。 @kriegaex

标签: java aspectj


【解决方案1】:

我可以看到你还在学习 Java,因为你不知道诸如此类的基本编程约定

  • 类名应以大写字母开头,
  • 变量、参数和字段的名称应易于理解,而不是单个字母。

您还使用特权方面的直接字段访问,而不是仅仅为您的类的字段创建公共 getter 方法并使用它们。 toString 方法也很有帮助,因为这样您就可以轻松地打印对象,而无需访问 getter 并制作自己的输出。

此外,在main 方法之后运行的建议是一个很好的实验,但没有多大意义。因为帐户所有者与您的应用程序中的帐户所有者之一同名,所以看起来您想入侵该帐户。我在那里评论了代码,以解释为什么它不能那样工作。

我还重构了您的应用程序类和方面,现在看起来像这样,而不改变功能:

package de.scrum_master.app;

public class Account {
  private String owner;
  private double balance;

  public Account(String owner, double balance) {
    this.owner = owner;
    this.balance = balance;
  }

  public void withdraw(double amount) {
    balance -= amount;
  }

  public void deposit(double amount) {
    balance += amount;
  }

  public String getOwner() {
    return owner;
  }

  public double getBalance() {
    return balance;
  }

  @Override
  public String toString() {
    return "Account[owner=" + owner + ", balance=" + balance + "]";
  }

  public static void main(String[] argv) {
    Account bossAccount = new Account("Boss", 2000);
    Account nerdAccount = new Account("Nerd", 1000);
    bossAccount.deposit(400);
    nerdAccount.withdraw(200);
    bossAccount.withdraw(300000);    // Cannot withdraw more than account balance
    nerdAccount.withdraw(-500000);   // Cannot withdraw a negative amount
    bossAccount.deposit(-123456);    // Cannot deposit a negative amount
    System.out.println(bossAccount);
    System.out.println(nerdAccount);
  }
}
package de.scrum_master.aspect;

import de.scrum_master.app.Account;

public aspect AccountAspect {

  // Withdrawal
  void around(Account account, double amount) :
    execution(void Account.withdraw(double)) &&
    target(account) &&
    args(amount)
  {
    if (amount > account.getBalance()) {
      System.out.println("Cannot withdraw more than account balance");
      return;
    }
    if (amount < 0) {
      System.out.println("Cannot withdraw a negative amount");
      return;
    }
    proceed(account, amount);
  }

  // Deposit
  void around(double amount) :
    execution(void Account.deposit(double)) &&
    args(amount)
  {
    if (amount < 0) {
      System.out.println("Cannot deposit a negative amount");
      return;
    }
    proceed(amount);
  }

  // This does not make any sense because
  //   1. it happens after the application ends (after leaving main method)
  //   2. Even though the account owner is the same as in the main method,
  //      it does not mean that by creating a new object with the same name
  //      the "Nerd" can manipulate the original account balance. You have to
  //      intercept the original Account object and manipulate it directly.
  after() : execution(public static void *.main(String[])) {
    System.out.println("--- after end of main program ---");
    Account account = new Account("Nerd", 3000);
    account.deposit(-100);
    System.out.println(account);
  }

  // TODO: PIN secret password
  // TODO: transaction record
}

控制台日志将是:

Cannot withdraw more than account balance
Cannot withdraw a negative amount
Cannot deposit a negative amount
Account[owner=Boss, balance=2400.0]
Account[owner=Nerd, balance=800.0]
--- after end of main program ---
Cannot deposit a negative amount
Account[owner=Nerd, balance=3000.0]

我不会为你做家庭作业,但会给你一些提示:

  • PIN(密码):Account 类需要一个字段pin,该字段可以在构造函数中设置,并且不应具有公共 getter 方法以避免任何人都可以访问 PIN。如果分配要求您不编辑基类而是通过 AOP 解决问题,您可以使用类型间定义 (ITD) 来添加私有字段和公共设置器,甚至可能为类添加额外的构造函数。接下来,您将添加一条建议,如果用户第一次尝试访问某个帐户的任何事务方法(例如 depositwithdraw),该建议将要求用户在控制台上输入 PIN。正确输入 PIN 后,他将能够继续,否则会出现错误消息并禁止交易。方面本身可以保留所有Account 对象的缓存(临时存储) - 可能您想使用Set&lt;Account&gt; - 在运行会话期间已成功验证,以避免用户必须输入 PIN再次使用同一个帐户。

  • 每个帐户的交易记录:同样,您可以使用 ITD 将类似 List&lt;TransactionRecord&gt; 的内容作为字段添加到 Account,使用空列表对其进行初始化,然后为每个帐户添加交易记录存款或取款。您还可以保持简单的概念证明,不创建 TransactionRecord 助手类,而只是使用 List&lt;Double&gt; 进行交易,记录存款的正数和取款的负数。带有“存款 123.45”或“取款 67.89”等元素的 List&lt;String&gt; 也是一种可行的选择。重要的是你的老师可以看到正确的方面逻辑。

【讨论】:

    猜你喜欢
    • 2016-11-21
    • 1970-01-01
    • 2019-07-22
    • 2014-08-27
    • 1970-01-01
    • 1970-01-01
    • 2015-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多