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设置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)
{
...
}
}
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我可以通过,但有几个,一个用于持久性,一个用于服务配置.我该怎么办?另外,每次创建这样的实例时我会创建一个全新的上下文,或者我错过了什么?
对此没有更好的解决方案吗?
任何帮助是极大的赞赏.
我认为发送激活电子邮件操作不是业务层的一部分,这里的域逻辑是帐户激活操作,那条逻辑应该存在于 DomainObjectwith name Account(activate()方法)中.该发送激活邮件动作的部分infrastructure或application层.
服务是处理帐户激活请求并连接业务层和其他人的对象.服务获取给定帐户,激活它们并执行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中,我们有两个工具来处理事件,ApplicationEventPublisher和ApplicationListener.
简短示例,发布域事件的服务:
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事件的更多信息.
| 归档时间: |
|
| 查看次数: |
11556 次 |
| 最近记录: |