业务逻辑(以及那是什么?)应该在哪里实现,以及如何使用Spring实现这一目标?

mar*_*2ch 7 java spring dependency-injection business-logic business-objects

我刚读这篇文章:

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

我觉得很棒.它很好地解释了层结构,我很高兴我正在使用的架构就是他所描述的.

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

第一:业务逻辑到底是什么?它不是什么?在他所说的文章中(并且他不是唯一的),业务逻辑应该进入域模型.所以一个Account类应该有一个activate()知道如何激活一个的方法Account.根据我的理解,这可能涉及一些持久性工作.但域模型不应该具有DAO的依赖性.只有服务层应该知道DAO.

那么,业务逻辑是域实体可以自己做什么的呢?就像activate()方法将active属性true设置dateActivatednew 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)
  {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

这跟他说的相反,我想,不是吗?

我还没有得到的是关于如何使用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);  
   }  
}
Run Code Online (Sandbox Code Playgroud)

如果我使用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(); 
Run Code Online (Sandbox Code Playgroud)

这不可靠而且非常麻烦,不是吗?每当我看到一个Account实例时,我都要问自己在哪里创建了这个对象.另外,如果我采用这种方法:我没有一个appContext.xml我可以通过,但有几个,一个用于持久性,一个用于服务配置.我该怎么办?另外,每次创建这样的实例时我会创建一个全新的上下文,或者我错过了什么?

对此没有更好的解决方案吗?

任何帮助是极大的赞赏.

mas*_*ted 7

我认为发送激活电子邮件操作不是业务层的一部分,这里的域逻辑是帐户激活操作,那条逻辑应该存在于 DomainObjectwith name Account(activate()方法)中.该发送激活邮件动作的部分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);
 }

}
Run Code Online (Sandbox Code Playgroud)

我可以建议的下一步是完全分离业务层和一层基础架构.这可以通过介绍业务事件来获得.服务不再需要执行发送电子邮件的操作,它会创建事件通知其他层有关帐户激活的事件.

在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));
 }

}
Run Code Online (Sandbox Code Playgroud)

和基础结构层上的域事件侦听器:

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);
  }
 }
Run Code Online (Sandbox Code Playgroud)

现在,您可以添加其他激活类型,日志记录,其他基础架构支持而无需更改,并污染您的域(业务)-layer.

啊,您可以在文档中了解有关spring事件的更多信息.