4

我只是讀這篇文章:業務邏輯(以及那是什麼?)應該在哪裏生存,以及如何用Spring來實現?

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

我覺得這很棒。它很好地解釋了層架構,我很高興我正在使用的架構非常符合他的描述。

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

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

那麼,業務邏輯就是一個域實體可以對自己做什麼?與activate()類似,方法會將active屬性設置爲true,並將dateActivated屬性設置爲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線域對象的例子。如果Account自己發送電子郵件,則需要這樣做。

鑑於此代碼:

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,我可以以電匯mailSender使用DependencyInjectionInterceptorFactoryBean。如果我使用JDBC來代替,那麼我真的會寫下以下繁瑣的代碼?另外,當我在MVC控制器中爲Account創建新實例時,讓我們假設將它填充到模型中?

BeanFactory beanFactory = new XmlBeanFactory( 
    new ClassPathResource("chapter3.xml")); 
    Account account = new Account(); 
    account.setEmail("[email protected]"); 
    ((AutowireCapableBeanFactory)beanFactory).applyBeanPropertyValues( 
     account, "accountPrototype"); 
    account.activate(); 

這不可靠,很麻煩,不是嗎?每當我看到一個Account的實例時,我都不得不問自己該創建對象的位置。此外,如果我採用這種方法:我沒有可以傳遞的一個appContext.xml,但有幾個,一個用於持久性,一個用於服務配置。我會怎麼做?另外,每創建一個這樣的實例或者我錯過了什麼,這會創建一個全新的上下文?

有沒有更好的解決方案呢?

任何幫助,非常感謝。

回答

5

我覺得發送激活郵件動作不是業務層的一部分,在這裏,在這裏你的域邏輯是賬號激活行動,那塊邏輯應該活在DomainObject與名稱Accountactivate()方法)。 發送激活郵件動作是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); 
} 

} 

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

在春天,我們有兩個工具來處理事件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); 
    } 
} 

現在,您可以添加其他激活類型,日誌等基礎的東西支持而不改變,並污染你的域名(業務)層。

啊,你可以在the documentation瞭解更多關於春季活動的信息。

+0

扼殺,謝謝你的回答。所以,基本上我的建議是真實的,即業務邏輯是「業務實體可以獨立完成而不使用其他層的東西」。其餘的是服務任務(或基礎設施或任何你稱之爲的)。對我來說有點意義,不過直覺上,我會打電話來決定是發送一封確認電子郵件還是不是「商業決策」,我想這就是讓我困惑的原因。 – marc82ch 2012-07-30 11:20:16

+1

是否發送確認電子郵件的決定 - 是的是「業務決策」,但發送不是業務任務。 :)我不確定這個決定是否是Account的職責範圍。這很可能是AccountService的一項任務。 – masted 2012-07-30 12:54:08

相關問題