簡體   English   中英

業務邏輯(以及那是什么?)應該在哪里實現,以及如何使用Spring實現這一目標?

[英]Where should business logic (and what is that?) really live and how to do that with Spring?

我剛讀這篇文章:

http://www.tutorialized.com/view/tutorial/Spring-MVC-Application-Architecture/11986

我覺得很棒。 它很好地解釋了層結構,我很高興我正在使用的架構就是他所描述的。

但有一件事,我似乎沒有得到:

第一:業務邏輯到底是什么?它不是什么? 在他所說的文章中(並且他不是唯一的),業務邏輯應該進入域模型。 因此, Account類應該有一個知道如何激活Accountactivate()方法。 根據我的理解,這可能涉及一些持久性工作。 但域模型不應該具有DAO的依賴性。 只有服務層應該知道DAO。

那么,業務邏輯是域實體可以自己做什么的呢? 就像activate()方法將active屬性設置為truedateActivated屬性設置為new Date() ,然后是服務的任務,首先調用account.activate()和第二個dao.saveAccount(account) 什么需要外部依賴關系到服務? 這就是我到目前為止所做的事情。

public AccountServiceImpl implements AccountService
{
  private AccountDAO dao;
  private MailSender mailSender;

  public void activateAccount(Account account)
  {
     account.setActive(true);
     account.setDateActivated(new Date());
     dao.saveAccount(account);
     sendActivationEmail(account);
  }
  private void sendActivationEmail(Account account)
  {
    ...
  }
}

這跟他說的相反,我想,不是嗎?

我還沒有得到的是關於如何使用像Account這樣的Spring wire域對象的示例。 如果賬戶自己發送電子郵件,則需要哪些。

鑒於此代碼:

import org.springframework.mail.MailSender;  
import org.springframework.mail.SimpleMailMessage;  

public class Account {  
   private String email;  
   private MailSender mailSender;  
   private boolean active = false;  

   public String getEmail() {  
      return email;  
   }  

   public void setEmail(String email) {  
      this.email = email;  
   }  

   public void setMailSender(MailSender mailSender) {  
      this.mailSender = mailSender;  
   }  

   public void activate() {  
      if (active) {  
      throw new IllegalStateException("Already active");  
      }  

      active = true;  
      sendActivationEmail();  
   }  

   private void sendActivationEmail() {  
      SimpleMailMessage msg = new SimpleMailMessage();  
      msg.setTo(email);  
      msg.setSubject("Congrats!");  
      msg.setText("You're the best.");  
      mailSender.send(msg);  
   }  
}

如果我使用Hibernate,我可以使用DependencyInjectionInterceptorFactoryBean來連接mailSender 如果我改用JDBC,我真的會編寫下面那些繁瑣的代碼嗎? 另外,當我在MVC控制器中為Account創建一個新實例時,讓我們說它填充到一個模型?

  BeanFactory beanFactory = new XmlBeanFactory(  
     new ClassPathResource("chapter3.xml"));  
  Account account = new Account();  
  account.setEmail("email@example.com");  
  ((AutowireCapableBeanFactory)beanFactory).applyBeanPropertyValues(  
        account, "accountPrototype");  
  account.activate(); 

這不可靠而且非常麻煩,不是嗎? 每當我看到一個Account實例時,我都要問自己在哪里創建了這個對象。 另外,如果我采用這種方法:我沒有一個appContext.xml我可以通過,但有幾個,一個用於持久性,一個用於服務配置。 我該怎么辦? 另外,每次創建這樣的實例或者我錯過了某些內容時,這會創建一個全新的上下文?

對此沒有更好的解決方案嗎?

任何幫助是極大的贊賞。

我認為發送激活電子郵件操作不是業務層的一部分,這里的域邏輯是帳戶激活操作,該邏輯應該存在於名為Accountactivate()方法)的DomainObject 發送激活電子郵件操作是infrastructureapplication層的一部分。

服務是處理帳戶激活請求並連接業務層和其他人的對象。 服務獲取給定帳戶,激活它們並執行MailSenderService的 發送激活電子郵件操作或類似的操作。

短樣本:

public AccountServiceImpl implements AccountService
{
 private AccountDAO dao;
 private MailSenderService mailSender;

 public void activateAccount(AccountID accountID)
 {
   Account account = dao.findAccount(accountID);
   ....
   account.activate();
   dao.updateAccount(account);
   ....

   mailSender.sendActivationEmail(account);
 }

}

我可以建議的下一步是完全分離業務層和一層基礎架構。 這可以通過介紹業務事件來獲得。 服務不再需要執行發送電子郵件的操作,它會創建事件通知其他層有關帳戶激活的事件。

在Spring中,我們有兩個工具來處理事件, ApplicationEventPublisherApplicationListener

簡短示例,發布域事件的服務:

public AccountActivationEvent extends ApplicationEvent {
    private Account account;

    AccountActivationEvent(Account account) {
       this.account = account;
    }

    public Account getActivatedAccount() {
       return account;
    }
}

public AccountServiceImpl implements AccountService, ApplicationEventPublisherAware
{
 private AccountDAO dao;
 private ApplicationEventPublisher epublisher;

 public void setApplicationEventPublisher(ApplicationEventPublisher epublisher) {
    this.epublisher = epublisher;
 }

 public void activateAccount(AccountID accountID)
 {
  Account account = dao.findAccount(accountID);
  ....
  account.activate();
  dao.updateAccount(account);
  ....

  epublisher.publishEvent(new AccountActivationEvent(account));
 }

}

和基礎結構層上的域事件偵聽器:

public class SendAccountActivationEmailEventListener 
      implements ApplicationListener<AccountActivationEvent> {

  private MailSenderService mailSender;

  .... 

  public final void onApplicationEvent(final AccountActivationEvent event) {
   Account account = event.getActivatedAccount():
    .... perform mail ...
   mailSender.sendEmail(email);
  }
 }

現在,您可以添加其他激活類型,日志記錄,其他基礎架構支持而無需更改,並污染您的域(業務)-layer。

啊,您可以在文檔中了解有關spring事件的更多信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM